我正在尝试做一些“模板元编程”的工作,以使c++函数更容易地向python公开。我想要做的是接受一个现有的函数,并生成一个字符串,其中包含有关返回类型和参数的信息(类型信息也可以)。
我使用的是一个基于(偷来的) 这篇wordpress文章的函数特性类,而不是对前几个参数的硬代码访问,而是对所有参数进行迭代。
我认为我需要一个模板函数,它为参数索引取一个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);
}在第一种情况下,在调用function_traits时使用getArgTypes结构,我不知道将什么指定为.Args模板参数在第二种情况下,MSVC抛出错误:
Error C1202 recursive type or function dependency context too complex如果这是一个愚蠢的问题,我对元编程/各种模板的东西完全陌生,很抱歉。如果有一个不那么迂回的解决方案,我也会感兴趣。
感谢您的阅读!
发布于 2015-08-16 15:16:02
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...> {};https://stackoverflow.com/questions/32036556
复制相似问题