获取C ++函数参数的类型

时间:2015-02-13 21:45:01

标签: c++ templates variadic-templates c++14 c++17

是否有标准的方法来获取函数的参数类型并将这些类型作为模板参数包传递?我知道这在C ++中是可行的,因为it has been done before

我希望通过C ++ 14或即将推出的C ++ 1z,在这里实现arg_types<F>...会有一种惯用的方法:

template <typename ...Params>
void some_function(); // Params = const char* and const char*

FILE* fopen(const char* restrict filename, const char* restrict mode);

int main(){
    some_function<arg_types<fopen>...>();
}

为了清楚起见,一个声称没有标准方法可以做到这一点的答案不是答案。如果没有答案,我宁愿在解决方案被添加到C ++ 500之前或者直到宇宙热死亡之前仍然没有答案,以先发生者为准:)

编辑:删除的答案指出我可以使用PRETTY_FUNCTION来获取参数类型的名称。但是,我想要实际的类型。不是那些类型的名称。

2 个答案:

答案 0 :(得分:13)

这种语法略有不同。

首先,因为类型比包更容易使用,所以类型包含包。 using type=types;只会将我的工作保存在生成​​types

的代码中
template<class...>struct types{using type=types;};

这是主力。它需要一个签名,并生成一个包含签名参数的types<?...>包。 3个步骤,所以我们可以得到很好的干净的C ++ 14esque语法:

template<class Sig> struct args;
template<class R, class...Args>
struct args<R(Args...)>:types<Args...>{};
template<class Sig> using args_t=typename args<Sig>::type;

这是语法差异。我们不是直接采用Params...,而是采用types<Params...>。这类似于“标签调度”模式,我们利用模板函数类型推导将参数移动到类型列表中:

template <class...Params>
void some_function(types<Params...>) {
}

我的fopen不同,因为我不想打扰#include内容:

void* fopen(const char* filename, const char* mode);

语法不是基于fopen,而是基于fopen类型。如果你有一个指针,你需要做decltype(*func_ptr)或某些事情。或者我们可以增加顶部来处理R(*)(Args...)以便于使用:

int main(){
  some_function(args_t<decltype(fopen)>{});
}

live example

请注意, 不能使用重载函数,也不能使用函数对象。

一般来说,这种事情是个坏主意,因为通常你知道你是如何与一个物体互动的。

如果你想获取一个函数(或函数指针)并从某个堆栈中的某个堆栈中弹出一些参数并根据它预期的参数或类似的东西调用它,上面只会有用。

答案 1 :(得分:3)

使用Boost.FunctionTypesstd::index_sequence。下面是打印函数func的参数类型的示例。您可以更改doit静态功能以执行您想要的操作。在行动here中查看。

template <typename FuncType>
using Arity = boost::function_types::function_arity<FuncType>;

template <typename FuncType>
using ResultType = typename boost::function_types::result_type<FuncType>::type;

template <typename FuncType, size_t ArgIndex>
using ArgType = typename boost::mpl::at_c<boost::function_types::parameter_types<FuncType>, ArgIndex>::type;

void func(int, char, double) {}

template <typename Func, typename IndexSeq>
struct ArgPrintHelper;

template <typename Func, size_t... Inds>
struct ArgPrintHelper<Func, integer_sequence<size_t, Inds...> >
{
  static void doit()
  {
    string typeNames[] = {typeid(ResultType<Arg>).name(), typeid(ArgType<Func, Inds>).name()...};
    for (auto const& name : typeNames)
      cout << name << " ";
    cout << endl;
  }
};

template <typename Func>
void ArgPrinter(Func f)
{
  ArgPrintHelper<Func, make_index_sequence<Arity<Func>::value> >::doit();
}

int main()
{
  ArgPrinter(func);
  return 0;
}

标题(向下移动以减少上述代码段中的噪音):

#include <boost/function_types/function_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/function_arity.hpp>

#include <algorithm>
#include <iostream>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <tuple>
#include <utility>
using namespace std;