在运行时使用函数转换类型列表
Transform typelist with function at runtime
我有一个类型列表。我想创建一个元组,其中包含对该列表中的每种类型调用函数的结果,然后将其用作另一个仿函数的参数。所以像这样:
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 是一个元组而不是参数包。编译器生成此错误:"there are no parameter packs available to expand"。我希望发生的事情是将该行扩展为:
func(*get_arg<int>(id), *get_arg<char>(id));
并使它适用于任意数量的参数。有什么办法可以得到那个结果吗?
这个问题看起来很相似,但并不能单独解决我的问题:"unpacking" a tuple to call a matching function pointer。我有一个类型列表,我想从中生成一个值列表以用作函数参数。如果我有值列表,我可以扩展它们并调用该问题中概述的函数,但我没有。
不确定那是你想要的。
我不知道如何在 call_func()
中扩展 params_type
的参数包,但是,如果您负担得起使用辅助结构和带有 C++14 的编译器。 ..
我准备了以下支持 return 类型的示例。
#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;
}
希望对您有所帮助。
我有一个类型列表。我想创建一个元组,其中包含对该列表中的每种类型调用函数的结果,然后将其用作另一个仿函数的参数。所以像这样:
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 是一个元组而不是参数包。编译器生成此错误:"there are no parameter packs available to expand"。我希望发生的事情是将该行扩展为:
func(*get_arg<int>(id), *get_arg<char>(id));
并使它适用于任意数量的参数。有什么办法可以得到那个结果吗?
这个问题看起来很相似,但并不能单独解决我的问题:"unpacking" a tuple to call a matching function pointer。我有一个类型列表,我想从中生成一个值列表以用作函数参数。如果我有值列表,我可以扩展它们并调用该问题中概述的函数,但我没有。
不确定那是你想要的。
我不知道如何在 call_func()
中扩展 params_type
的参数包,但是,如果您负担得起使用辅助结构和带有 C++14 的编译器。 ..
我准备了以下支持 return 类型的示例。
#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;
}
希望对您有所帮助。