C ++: извлечение типа параметра из статической функции в структуре - PullRequest
0 голосов
/ 29 ноября 2018

Скажем, у меня что-то вроде этого:

template<typename T, typename R>
struct MyStruct {
    static R myfunc(T);
};

struct MyStructInst: S<int, double> {
    static double myfunc(int i) { return i; }
};

Затем, позже, у меня есть шаблон, который принимает M, тип, который, как я предполагаю, имеет статическую функцию myfunc с одним параметром (например,MyStructInst).Я хочу извлечь тип параметра и тип результата myfunc:

template<typename M,
    typename ParamType = ???,
    typename ResultType = decltype(declval(M::myfunc))> // I think this works?
struct MyStruct2 {
    ...
};

Какой самый простой способ получить ParamType?

1 Ответ

0 голосов
/ 29 ноября 2018

А как насчет

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>{}, "!");
 }
...