我有一个类型列表。 我想创建一个元组,其结果是在该列表中的每个类型上调用一个函数,然后将其用作另一个函子的参数。 所以像这样:
template<typename F> struct function_traits; template<typename T, typename R, typename... Args> struct function_traits<R(T::*)(Args...) const> { using return_type = R; using param_types = std::tuple<Args...>; }; template<typename T> struct function_traits : public function_traits<decltype(&T::operator())> {}; template <typename T> T* get_arg(int id) { // Actual implementation omitted. Uses the id parameter to // do a lookup into a table and return an existing instance // of type T. return new T(); } template <typename Func> void call_func(Func&& func, int id) { using param_types = function_traits<Func>::param_types>; func(*get_arg<param_types>(id)...); // <--- Problem is this line } call_func([](int& a, char& b) { }, 3);问题是, func(*get_arg<param_types>(id)...); 实际上并没有编译,因为param_types是一个元组而不是参数包。 编译器生成此错误:“没有可用于展开的参数包”。 我希望发生的事是为了扩展到:
func(*get_arg<int>(id), *get_arg<char>(id));并为任何数量的争论做这项工作。 有什么方法可以得到这个结果吗?
这个问题看起来很相似,但并不能解决我自己的问题: “解包”一个元组来调用一个匹配的函数指针 。 我有一个类型列表,从中我想要生成一个值列表作为函数参数使用。 如果我有价值清单,我可以扩展它们并按照该问题中所述的那样调用函数,但是我不这样做。
I have a typelist. I would like to create a tuple with the results of calling a function on each type in that list and then use that as arguments to another functor. So something like this:
template<typename F> struct function_traits; template<typename T, typename R, typename... Args> struct function_traits<R(T::*)(Args...) const> { using return_type = R; using param_types = std::tuple<Args...>; }; template<typename T> struct function_traits : public function_traits<decltype(&T::operator())> {}; template <typename T> T* get_arg(int id) { // Actual implementation omitted. Uses the id parameter to // do a lookup into a table and return an existing instance // of type T. return new T(); } template <typename Func> void call_func(Func&& func, int id) { using param_types = function_traits<Func>::param_types>; func(*get_arg<param_types>(id)...); // <--- Problem is this line } call_func([](int& a, char& b) { }, 3);The problem is that func(*get_arg<param_types>(id)...); doesn't actually compile since param_types is a tuple and not a parameter pack. The compiler generates this error: "there are no parameter packs available to expand". What I would liked to have happened is for that line to expand to:
func(*get_arg<int>(id), *get_arg<char>(id));And to have that work for any number of arguments. Is there any way to get that result?
This question seems similar but does not solve my problem by itself: "unpacking" a tuple to call a matching function pointer. I have a type list and from that I want to generate a list of values to use as function arguments. If I had the list of values I could expand them and call the function as outlined in that question, but I do not.
最满意答案
不确定那是你想要的。
我不知道如何在call_func()扩展call_func()的参数包,但是,如果您使用C ++ 14的辅助结构和编译器...
我准备了以下支持返回类型的示例。
#include <tuple> template<typename F> struct function_traits; template<typename T, typename R, typename... Args> struct function_traits<R(T::*)(Args...) const> { using return_type = R; using param_types = std::tuple<Args...>; }; template<typename T> struct function_traits : public function_traits<decltype(&T::operator())> {}; template <typename T, typename ... Args> T get_arg (std::tuple<Args...> const & tpl) { return std::get<typename std::decay<T>::type>(tpl); } template <typename ...> struct call_func_helper; template <typename Func, typename Ret, typename ... Args> struct call_func_helper<Func, Ret, std::tuple<Args...>> { template <typename T, typename R = Ret> static typename std::enable_if<false == std::is_same<void, R>::value, R>::type fn (Func const & func, T const & t) { return func(get_arg<Args>(t)...); } template <typename T, typename R = Ret> static typename std::enable_if<true == std::is_same<void, R>::value, R>::type fn (Func const & func, T const & t) { func(get_arg<Args>(t)...); } }; template <typename Func, typename T, typename R = typename function_traits<Func>::return_type> R call_func (Func const & func, T const & id) { using param_types = typename function_traits<Func>::param_types; return call_func_helper<Func, R, param_types>::fn(func, id); } int main() { call_func([](int const & a, char const & b) { }, std::make_tuple(3, '6')); return 0; }希望这可以帮助。
Not sure that is what do you want.
I don't know how to expand, inside call_func(), the parameters pack of params_type but, if you afford the use of a helper struct and a compiler with C++14...
I've prepared the following example with support for return type.
#include <tuple> template<typename F> struct function_traits; template<typename T, typename R, typename... Args> struct function_traits<R(T::*)(Args...) const> { using return_type = R; using param_types = std::tuple<Args...>; }; template<typename T> struct function_traits : public function_traits<decltype(&T::operator())> {}; template <typename T, typename ... Args> T get_arg (std::tuple<Args...> const & tpl) { return std::get<typename std::decay<T>::type>(tpl); } template <typename ...> struct call_func_helper; template <typename Func, typename Ret, typename ... Args> struct call_func_helper<Func, Ret, std::tuple<Args...>> { template <typename T, typename R = Ret> static typename std::enable_if<false == std::is_same<void, R>::value, R>::type fn (Func const & func, T const & t) { return func(get_arg<Args>(t)...); } template <typename T, typename R = Ret> static typename std::enable_if<true == std::is_same<void, R>::value, R>::type fn (Func const & func, T const & t) { func(get_arg<Args>(t)...); } }; template <typename Func, typename T, typename R = typename function_traits<Func>::return_type> R call_func (Func const & func, T const & id) { using param_types = typename function_traits<Func>::param_types; return call_func_helper<Func, R, param_types>::fn(func, id); } int main() { call_func([](int const & a, char const & b) { }, std::make_tuple(3, '6')); return 0; }Hope this helps.
更多推荐
发布评论