Final
Final

Reputation: 51

Weird template and member function pointer error (C2373, C2530)

I came up with the following code when learning signal & slot, template, and function pointer.

Basically I am trying to make 2 classes, the base one will takes normal function pointers while the derived one will takes member function and wrap it up with a normal function, then pass it to the base class for invoking.

Here is the code:

#include<iostream>

struct foo {
    void onNotify(int a, int b) {
        std::cout << "member function: this=" << this << " a=" << a << " b=" << b << "\n";
    }
};

void onNotify(void*, int a, int b) {
    std::cout << "normal function: no context needed! a=" << a << " b=" << b << "\n";
}


// invoker that will takes normal functions.
template <typename...>
class invoker{
public:
    invoker(void (*fptr)(void*, int, int), void* context){
        fptr(context, 1, 2);
    }
private:
    invoker(){}
};


// invoker that will takes member functions.
template<class T>
class invoker<T> : public invoker<>{
public:
    invoker<T>(T* context) : invoker<>(&forwarder, context){}
private:
    invoker<T>(){}
    static void forwarder(void* context, int i0, int i1) {
        static_cast<T*>(context)->onNotify(i0, i1);
    }
};

int main()
{
    invoker<>(&onNotify, 0);        // OK.

    invoker<foo>(new foo);          // OK.
    invoker<foo>(0);                // OK.

    foo foo_;

    auto f = invoker<foo>(&foo_);   // OK.

    // Errors:
    //      C2373 : 'foo_' : redefinition; different type modifiers.
    //      C2530 : 'foo_' : reference must be initialized.
    invoker<foo>(&foo_);            // ERROR!

    return 0;
}

My questions are:

1) What is causing the compile error?

2) Why invoker<foo>(0); will actually run without error?

Thanks in advance!

Upvotes: 1

Views: 123

Answers (1)

vitaut
vitaut

Reputation: 55685

1) The problem is that

invoker<foo>(&foo_);

is parsed as a definition of variable foo_ that has type invoker<foo>& rather than a call to the ctor of invoker<foo>. There is a number of ways to fix this, for example, use extra parentheses:

(invoker<foo>)(&foo_);

2) The code

invoker<foo>(0);

compiles without an error because it's unambiguous (it can't be interpreted as a declaration).

Upvotes: 2

Related Questions