This question already has an answer here:
-
Disambiguate overloaded member function pointer being passed as template parameter
1 answer
I have this code:
struct Foo
{
int print(int a, double b);
int print(int a);
void print();
void print(int a, int b, int c);
void other();
};
I can call
decltype(&Foo::other)
but calling
decltype(&Foo::print)
end with error, which is clear to me.
But how can I specify more "closely" which of the four print
methods, I want to resolve to decltype
?
I want to further use this in
template <class MT>
struct method_info;
template <class T, class Res, class... Args>
struct method_info<Res(T::*)(Args...)>
{
typedef std::tuple<Args&&...> args_tuple;
typedef T ClassType;
typedef Res RetVal;
};
template <class MethodType>
void func() {
typedef method_info<MethodType> MethodInfo;
.....
}
func<decltype(&Foo::other)>();
....
More "closely", as far as I understand, means you want to specify the function arguments of print
. That is, for example, you select int, int
, then get back the result-type of Foo{}.print(int{},int{})
, and thereafter construct a function pointer from all the available information.
Here is an alias template which does that for you in a general way:
template<typename ... Args>
using ptr_to_print_type = decltype(std::declval<Foo>().print(std::declval<Args>() ...)) (Foo::*)(Args ...);
You could also use std::result_of
instead of the std::declval
stuff, but I like the latter more.
You can use the above as
func<ptr_to_print_type<int,int> >();
EDIT: as asked for by @JavaLover, which btw seems like an unsuitable name for such horrible C++ shit :-), here is the same as above using std::result_of
(untested now tested and wrong):
//------ does not compile for overloaded functions --------
template<typename ... Args>
using ptr_to_print_type = std::result_of_t<decltype(&Foo::print)(Foo, Args ...)> (Foo::*)(Args ...)
//------ does not compile for overloaded functions --------
You could further abstract away the Foo
but not the print
(unless you're using macros).
Not sure about the exact syntax but, in case of method name overloading, you should cast the pointer; something like
static_cast<void(Foo::*)(int, int, int)>(&Foo::print);
In you're interested only in type, should be the template value of the cast
void(Foo::*)(int, int, int)