简体   繁体   中英

<unresolved overloaded function type> with member function pointer and templates

sorry for my problem to be somewhat complicated, here it is:

I have an helper struct that hold any non-type template parameter that is declared like this:

template<typename T, T t>
struct Method {
    using Type = T;
    constexpr static T method = t;
};

I'm using it to store a member function pointer to use at compile-time.

Then, I have a class called TestClass that has a typedef to the Method type with one of it's method as parameter:

struct TestClass {
    void setFoo(int n) {}

    using MethodToCall = Method<decltype(&TestClass::setFoo), &TestClass::setFoo>;
};

Everything is okay at this point, and I can call it like this:

(tc.*TestClass::MethodToCall::method)(6); // compiles and runs

Then, there is the problem: I have another member function that takes a method as a template parameter again, and I'm trying to get a pointer from it. It works only If I put the function pointers directly.

struct Caller {
    template<typename T, T t>
    void callme(TestClass& test) {
        (test.*t)(6);
    }
};

template<typename F, typename T, typename... Args>
auto call(F f, T t, Args&&... args) -> decltype((t.*f)(std::forward<Args>(args)...)) {
    (t.*f)(std::forward<Args>(args)...);
}

int main() {
    Caller c;
    TestClass tc;

    (tc.*TestClass::MethodToCall::method)(6);

    //call(&Caller::callme<TestClass::MethodToCall::Type, TestClass::MethodToCall::method>, c, tc);
    call(&Caller::callme<decltype(&TestClass::setFoo), &TestClass::setFoo>, c, tc);

    return 0;
}

The three first call won't work. Why is this? How can I fix it? If I uncomment the first call, the compile gives me this error:

main.cpp: In function 'int main()':
main.cpp:40:96: error: no matching function for call to 'call(<unresolved overloaded function type>, Caller&, TestClass&)'
     call(&Caller::callme<TestClass::MethodToCall::Type, TestClass::MethodToCall::method>, c, tc);
                                                                                                ^
main.cpp:30:6: note: candidate: template<class F, class T, class ... Args> decltype (call::t.*call::f((forward<Args>)(call::args)...)) call(F, T, Args&& ...)
 auto call(F f, T t, Args&&... args) -> decltype((t.*f)(std::forward<Args>(args)...)) {
      ^
main.cpp:30:6: note:   template argument deduction/substitution failed:
main.cpp:40:96: note:   couldn't deduce template parameter 'F'
     call(&Caller::callme<TestClass::MethodToCall::Type, TestClass::MethodToCall::method>, c, tc);
                                                                                                ^

The full code can be found here: http://coliru.stacked-crooked.com/a/821c5b874b45ffb9

Thanks a lot!

I have found the mistake. You can't send a member function pointer to a template parameter that is stored in a variable, even a constexpr one.

constexpr auto theMethod = &TestClass::setFoo;

// won't work
call(&Caller::callme<decltype(theMethod), theMethod>);

In a template parameter that is a member function pointer, it is required that it is wrote directly:

constexpr auto theMethod = &TestClass::setFoo;

// won't work
call(&Caller::callme<decltype(theMethod), &TestClass::setFoo>);

My solution was to pass around an std::integral_constant instead of the function pointer directly.

using methodType = std::integral_constant<decltype(&TestClass::setFoo), &TestClass::setFoo>;

call(&Caller::callme<methodType>);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM