А как насчет
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
{ };
?
Я имею в виду ... если вы заявляете (нет необходимости реализовывать это, потому что используется только внутри decltype()
, поэтому тольковозвращаемый тип важен) функция, которая получает тип функции (я помню, что указатель на метод static подобен указателю на традиционную функцию), который получает один или несколько аргументов и возвращает тип первогоаргумент
template <typename R, typename A0, typename ... As>
constexpr A0 firstArg (R(*)(A0, As...));
с заданным типом имени шаблона M
, вы можете получить первый параметр метода myFunc()
(если есть) с помощью
typename PT = decltype(firstArg(&M::myfunc))
с учетом PT
(тип параметра первого типа) вы можете получить возвращаемый тип, просто имитируя (внутри decltype()
, используя std::declval()
) вызов myfunc()
с объектом типа PT
typename RT = decltype(M::myfunc(std::declval<PT>()))
.ниже приводится полный пример компиляции
#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>{}, "!");
}