迭代function_traits参数
Iterating through function_traits arguments
我正在尝试做一些"模板元编程"的东西,使c++函数暴露给python更容易一点。我想做的是接受一个现有的函数,并生成一个字符串,其中包含有关其返回类型和参数的信息(typeinfo也可以)。
我正在使用一个基于(从)这篇wordpress文章的函数特征类,但不是硬代码访问前几个参数,我想遍历它们。
我收集到我需要创建一个模板函数,该函数为参数index接受size_t值(因为它必须是常量),但这就是我有点迷失的地方。
我写了一些代码,但是我不能让它在最基本的情况下工作(更不用说我所追求的一般情况了。)
// The stolen function_traits struct...thing
template<typename T>
struct function_traits;
template<typename R, typename ...Args>
struct function_traits<std::function<R(Args...)>>
{
static const size_t nargs = sizeof...(Args);
using result_type = R;
template <size_t i>
struct arg
{
using type = typename std::tuple_element<i, std::tuple<Args...>>::type;
};
};
// The function of interest
int foo(float x) {
return int(x);
}
// Recurse until one argument is left, appending the type name
// to the referenced string being passed in
template<size_t argIdx, typename R, typename ... Args>
void getArgTypes(std::string& ref)
{
using fun = function_traits<std::function<R(Args...)> >;
if (argIdx == 1)
ref.append(typeid(fun::arg<0>).name()).append("n");
else {
ref.append(typeid(fun::arg<argIdx-1>).name()).append("n");
getArgTypes<argIdx - 1, R, Args...>(ref);
}
}
// My test of the template function
void test() {
std::string f = "";
// What I'd like to do
using fun = function_traits<std::function<decltype(foo)> >;
getArgTypes<fun::nargs, fun::result_type, ? ? ? >;
// But I can't even do this!
getArgTypes<1, float, int>(f);
}
在第一种情况下,我在调用getArgTypes时使用我的function_traits结构,我不知道该把什么指定为…Args模板参数。在第二种情况下,MSVC抛出错误:
Error C1202 recursive type or function dependency context too complex
我对这个元编程/可变模板的东西完全陌生,所以很抱歉,如果这是一个愚蠢的问题。如果有不那么迂回的解决办法,我也会感兴趣的。
感谢您的阅读!
-
if (argIdx == 1)
不能作为运行时条件。它必须更改为编译时的std::enable_if
。这就是错误的来源:编译器试图无休止地实例化(递归地没有停止条件)getArgType
函数模板。 -
所有依赖类型名称必须用
typename
关键字宣布,而那些引用模板的必须用template
关键字宣布,例如用typename fun::template arg<0>
代替fun::arg<0>
。 -
fun::arg<0>
本身是一个嵌套type
定义的结构体。使用typename fun::template arg<0>::type
语法访问。 -
function_traits::arg<N>::type
的扩展可以通过索引技巧来完成,特别是typename F::template arg<Is>::type...
。
#include <string>
#include <typeinfo>
#include <functional>
#include <utility>
#include <cstddef>
template <size_t argIdx, typename R, typename... Args>
auto getArgTypes(std::string& ref)
-> typename std::enable_if<argIdx == 1>::type
{
using fun = function_traits<std::function<R(Args...)> >;
ref.append(typeid(typename fun::template arg<0>::type).name()).append(" ");
}
template <size_t argIdx, typename R, typename... Args>
auto getArgTypes(std::string& ref)
-> typename std::enable_if<argIdx != 1>::type
{
using fun = function_traits<std::function<R(Args...)> >;
ref.append(typeid(typename fun::template arg<argIdx-1>::type).name()).append(" ");
getArgTypes<argIdx - 1, R, Args...>(ref);
}
template <typename F, std::size_t... Is>
void test2(std::index_sequence<Is...>)
{
std::string s;
getArgTypes<F::nargs, typename F::result_type, typename F::template arg<Is>::type...>(s);
std::cout << s;
}
void test()
{
using F = function_traits<std::function<decltype(foo)>>;
test2<F>(std::make_index_sequence<F::nargs>{});
}
非常基本的index_sequence
实现如下:
template <std::size_t...> struct index_sequence {};
template <std::size_t N, std::size_t... Is> struct make_index_sequence : make_index_sequence<N-1, N-1, Is...> {};
template <std::size_t... Is> struct make_index_sequence<0, Is...> : index_sequence<Is...> {};
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 使用指向成员的指针将成员函数作为参数传递
- 类型 traits,用于检查参数包中的所有类型是否都是可复制构造的
- 对采用"traits"模板参数的对象进行单元测试