首页 > 解决方案 > C++:从结构中的静态函数中提取参数类型

问题描述

说我有这样的事情:

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

标签: c++templatesc++17template-meta-programmingtemplate-argument-deduction

解决方案


关于什么

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 
 { };

?

我的意思是......如果你声明(不需要实现它,因为只在 a 内部使用decltype(),所以只有返回的类型很重要)接收函数类型的函数(我记得指向静态方法的指针就像一个指向传统函数的指针)接收一个或多个参数并返回第一个参数的类型

template <typename R, typename A0, typename ... As>
constexpr A0 firstArg (R(*)(A0, As...));

给定模板 typename 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>{}, "!");
 }

推荐阅读