获取C++函数参数类型
有没有一种标准的方法来获取函数参数的类型并将这些类型作为模板参数包进行传递?我知道这在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
获取参数类型的名称。不过,我想要真实的类型。不是那些类型的名字。
解决方案
此语法略有不同。
首先,因为类型比包(一种容纳包的类型)更易于使用。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...>
。这类似于"Tag Dispatching"模式,在该模式中,我们利用模板函数类型演绎将参数移动到类型列表中:
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。
请注意,这不适用于重载函数,也不适用于函数对象。
一般来说,这种事情不是好主意,因为通常您知道如何与对象交互。
仅当您希望将函数(或函数指针)从某个堆栈的某个位置弹出一些参数并根据其预期的参数或类似的参数调用它时,上述操作才有用。
相关文章