我一直在搜索SO和其他论坛,寻找确定lambda的参数和返回类型的方法,然后对这些参数进行操作,以便对已经存在的对象的repo进行类型查找实例化。关键是要创建一种方法来对某些任意定义的lambda表达式进行依赖注入。例如,如果我有以下内容:
auto lambda = [] (MyObject o) -> string { return o.name(); };
我可以确定lambda的参数类型,并查找类型为MyObject
的相应对象,然后调用lambda
“自动”传递该对象。
到目前为止,我已经找到了使用以下模板确定lambdas参数列表类型和返回类型的方法:
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
// For generic types, directly use the result of the signature of its 'operator()'
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
enum { arity = sizeof...(Args) };
// arity is the number of arguments.
typedef ReturnType result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
// the i-th argument is equivalent to the i-th tuple element of a tuple
// composed of those arguments.
};
};
我在this SO发现的帖子(非常整洁)。
现在,我想做的是实现某种类似于以下的编译时间:
// first get the type of the lambda using the above 'function_traits' template
typedef function_traits<decltype(lambda)> traits;
// now iterate over the traits and get the type of each argument, then print out the type name
for (size_t i = 0u; i < size_t(traits::arity); ++i)
{
// The point to focus on here is `traits::args<i>::type`
std::cout << typeid(traits::args<i>::type).name() << std::end;
}
我上面发布的内容是不可能的。上面代码中的问题是i
不是常量,并且在运行时进行评估,而不是编译时(评估此模板魔法的其余部分)。我尝试了一些不同的方法来试图找到一种方法(它们之间的模板递归),但我找不到能够完全符合我想要的解决方案。
所以,问题的根源在于,你如何“迭代”模板?我是TMP的新手,并且从运行时到编译时逻辑的精神转变一直是一个挑战。如果有人对新手有一些建议会很棒。
答案 0 :(得分:1)
使用C ++ 14,您可以:
namespace detail
{
template <typename T, std::size_t ... Is>
void display(std::index_sequence<Is...>)
{
std::initializer_list<int>{((std::cout << typeid(typename T::template arg<Is>::type).name() << std::endl), 0)...};
}
}
template <typename T>
void display()
{
detail::display<T>(std::make_index_sequence<T::arity>());
}
并使用它:
using traits = function_traits<decltype(lambda)>;
display<traits>();
如果你坚持使用C ++ 11,那么有很多地方可以找到make_index_sequence
和index_sequence
的实现