Say I have something like this:
template<typename T, typename R>
struct MyStruct {
static R myfunc(T);
};
struct MyStructInst: S<int, double> {
static double myfunc(int i) { return i; }
};
Then later, I have a template that takes M
, a type that I will assume has a static myfunc
function with one parameter (e.g. MyStructInst
). I want to extract the parameter type and the result type of myfunc
:
template<typename M,
typename ParamType = ???,
typename ResultType = decltype(declval(M::myfunc))> // I think this works?
struct MyStruct2 {
...
};
What's the easiest way to get ParamType
?
What about
template <typename R, typename A0, typename ... As>
constexpr A0 firstArg (R(*)(A0, As...));
template <typename M,
typename PT = decltype(firstArg(&M::myfunc)),
typename RT = decltype(M::myfunc(std::declval<PT>()))>
struct MyStruct2
{ };
?
I mean... if you declare (there is no needs to implement it because is used only inside a decltype()
, so only the returned type is important) a function that receive a function type (i remember that a pointer to a static method is like a pointer to a traditional function) that receive one or more arguments and return the type of the first argument
template <typename R, typename A0, typename ... As>
constexpr A0 firstArg (R(*)(A0, As...));
given a template typename M
, you can obtain the first parameter of the myFunc()
method (if any) with
typename PT = decltype(firstArg(&M::myfunc))
Given PT
(the type of the first type parameter) you can obtain the returned type simply simulating (inside decltype()
, using std::declval()
) a call to myfunc()
with a object of type PT
typename RT = decltype(M::myfunc(std::declval<PT>()))
The following is a full compiling example
#include <string>
#include <type_traits>
template <typename T, typename R>
struct MyStruct
{ static R myfunc(T); };
struct MyStructInst
{ static double myfunc(int i) { return i; } };
template <typename R, typename A0, typename ... As>
constexpr A0 firstArg (R(*)(A0, As...));
template <typename M,
typename PT = decltype(firstArg(&M::myfunc)),
typename RT = decltype(M::myfunc(std::declval<PT>()))>
struct MyStruct2
{ using type1 = PT; using type2 = RT; };
int main ()
{
static_assert( std::is_same<int,
typename MyStruct2<MyStructInst>::type1>{}, "!");
static_assert( std::is_same<double,
typename MyStruct2<MyStructInst>::type2>{}, "!");
static_assert( std::is_same<long,
typename MyStruct2<MyStruct<long, std::string>>::type1>{}, "!");
static_assert( std::is_same<std::string,
typename MyStruct2<MyStruct<long, std::string>>::type2>{}, "!");
}