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.