3

I have an assignment about linked list and template where there are functions with strange parameters which are mandatory. I couldn't find online document about it and any provided materials are appreciated.

I have tried to assign op with another address and then it compiled just fine but I couldn't call it.

template <class T> struct L1Item {
  T data;
  L1Item<T> *pNext;
  L1Item() : pNext(NULL) {}
  L1Item(T &a) : data(a), pNext(NULL) {}
};

template <class T> class L1List {
  L1Item<T> *_pHead; // The head pointer of linked list
  size_t _size;      // number of elements in this list
public:
  void traverse(void (*op)(T &)) {
    // TODO: Your code goes here
  }
  void traverse(void (*op)(T &, void *), void *pParam) {
    // TODO: Your code goes here
    //    string *Req = static_cast<string *>(pParam);
    //    if (*Req == "find city's id") {
    //        op = this->_pHead;
    //    };
  }
};
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Daanturo
  • 124
  • 2
  • 7
  • 3
    related: https://stackoverflow.com/questions/2592137/what-is-the-point-of-function-pointers Trying to find a better target for a dupe – NathanOliver Sep 25 '19 at 12:28
  • 3
    Search for *function pointers*. – Some programmer dude Sep 25 '19 at 12:29
  • 2
    There's this [translator](https://cdecl.org/?q=void+%28*op%29%28int+%26%2C+void+*%29) from C (and bits of C++) to English. – Yksisarvinen Sep 25 '19 at 12:30
  • See also [this FAQ](https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types). – metal Sep 25 '19 at 12:35
  • 5
    It's amazing that someone would give you this assignment without having previously explained the function pointer syntax. – Useless Sep 25 '19 at 12:42
  • @Useless - Indeed, function pointer syntax is probably one of the top 5 causes of confusion for students of C++! – Adrian Mole Sep 25 '19 at 12:54
  • 3
    Rant: It amazes me sometimes how bad teachers are at teaching c++. I think this is one reason why the langauge isn't used more widespread. It's as if some teachers are at point where they teach 'C with classes' (actually one of the first c++ versions was called that) and not c++. If you give someone a course of Java - it would be insane to start teaching them bytecode (even though the teacher may know bytecode really well). Perhaps not a good example but you get my point. It should be the other way around ! – darune Sep 25 '19 at 12:55

2 Answers2

6

The code void (*op)(T &) declares op as a pointer to a function taking a reference to a type T as an argument; void (*op)(T &, void *) is similar but with an extra argument of type void*.

Rather than trying to assign a pointer to an object to it in your (commented-out) code, op = this->_pHead; you should be calling the function passed. Something like this, for example:

void traverse(void (*op)(T &, void *), void *pParam) {
// TODO: Your code goes here
    op(pHead->data, pParam); // First parameter is a T passed by reference
}

Elsewhere in your code, when you actually call traverse, you would need to give, as its first argument, (the address of) a function that you (or somebody) has defined; for example:

template <class T> void myFunc(T& obj, void *pParam) {
    string *Req = static_cast<string *>(pParam);
    if (*Req == "find city's id") {
    // do something with/to "obj"
    }
}
//...
traverse(myFunc, pString);
// ...

Feel free to ask for further explanation (but also read the comments given in your question)!

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • 1
    It's a pointer to a function, and there needs to be a function that it points to. In this case, the function needs to be passed in when traverse() is called – DanS Sep 25 '19 at 12:40
  • @DanS Thanks for the comment! I've expanded my answer to incorporate your suggestion. – Adrian Mole Sep 25 '19 at 12:47
1

This:

void traverse(void (*op)(T &)) {
  // TODO: Your code goes here
}

is a function declaration that has one parameter of pointer to the function type void ( * )(T &).

The declaration would look more simple if instead of the function pointer there will be a function type as for example:

void traverse( void op( T & ) ) {
    // TODO: Your code goes here
}

The compiler implicitly converts the function type to pointer to the function type.

This:

void traverse(void (*op)(T &, void *), void *pParam) {
    // TODO: Your code goes here
    //    string *Req = static_cast<string *>(pParam);
    //    if (*Req == "find city's id") {
    //        op = this->_pHead;
    //    };
}

is also a function declaration with two parameters the first of which has a pointer to function type.

Again instead of a function pointer there could be declared a parameter of a function type:

void traverse( void op(T &, void *), void *pParam ) {
   // TODO: Your code goes here
   //    string *Req = static_cast<string *>(pParam);
   //    if (*Req == "find city's id") {
   //        op = this->_pHead;
   //    };
}

That makes the declaration clearer.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335