如何以元组 b 作为参数为元组(充当类型列表)中的每个类型调用模板函数
How to call a templated function for each type in a tuple (acting as type list) with tuple b as argument
如何使用参数(例如另一个元组)为类型列表中的每个类型调用模板函数?
给出的是一个类型列表 std::tuple<T1, T2, T3, ...>
和一个包含数据的 std::tuple
。
template <typename T>
void doSomething (const auto& arg) {
std::cout << __PRETTY_FUNCTION__ << '\n';
}
template <typename T> struct w {T v; w(T _v) : v{_v} {}};
int main () {
using types = std::tuple<int, char, float, double, w<int>, w<float>>; // used as type list
constexpr auto data = std::make_tuple(1, 2, 3.0, 4.0f, w(5.0));
// call doSomething<T>(data) for each type in types
// like
// someFunctor<types>(doSomething, data);
}
我目前的想法是像 appreach 这样的仿函数,它接收类型列表以提取下一个类型,并且 std::tuple<Ts>
有一个 operator ()
来为每个 T 调用 doSomething<T>(args)
。
template<template<typename...> typename TL, typename... Ts>
struct someFunctor {
template<typename... Args>
static constexpr void operator() (Args&&... args) {
(doSomething<Ts>(std::forward<Args>(args)...), ...);
}
};
不确定这是否是最明智的方法。到目前为止,脑雾阻碍了我的工作。
使用模板偏特化提取类型列表的类型,然后使用fold-expression调用具有不同模板参数的doSomething
template<typename Tuple>
struct someFunctor;
template<typename... Args>
struct someFunctor<std::tuple<Args...>> {
template<class T>
constexpr void operator()(T&& x) {
(doSomething<Args>(std::forward<T>(x)), ...);
}
};
using types = std::tuple<int, char, float, double, w<int>, w<float>>;
constexpr auto data = std::make_tuple(1, 2, 3.0, 4.0f, w(5.0f));
someFunctor<types>()(data);
下面是一小段代码:
using types = std::tuple<int, char, float, double, w<int>, w<float>>;
constexpr auto data = std::make_tuple(1, 2, 3.0, 4.0f, w(5.0));
[&]<template<typename...> class TL, typename... Ts>(TL<Ts...>*) {
// Now have a parameter pack of `Ts`
(doSomething<Ts>(data), ...);
}((types*) nullptr);
并变成可重复使用的函数,你可以这样做:
template<typename types, typename Functor, typename... Args>
constexpr void mapTypeList(Functor&& f, Args&&... args) {
[&]<template<typename...> class TL, typename... Ts>(TL<Ts...>*) {
((void) f.template operator()<Ts>(std::forward<Args>(args)...), ...);
}(static_cast<types*>(nullptr));
}
// You need to wrap `doSomething` in a lambda
mapTypeList<types>([]<typename T>(const auto& data) { doSomething<T>(data); }, data);
// or maybe capturing data:
mapTypeList<types>([&]<typename T>() { doSomething<T>(data); });
如何使用参数(例如另一个元组)为类型列表中的每个类型调用模板函数?
给出的是一个类型列表 std::tuple<T1, T2, T3, ...>
和一个包含数据的 std::tuple
。
template <typename T>
void doSomething (const auto& arg) {
std::cout << __PRETTY_FUNCTION__ << '\n';
}
template <typename T> struct w {T v; w(T _v) : v{_v} {}};
int main () {
using types = std::tuple<int, char, float, double, w<int>, w<float>>; // used as type list
constexpr auto data = std::make_tuple(1, 2, 3.0, 4.0f, w(5.0));
// call doSomething<T>(data) for each type in types
// like
// someFunctor<types>(doSomething, data);
}
我目前的想法是像 appreach 这样的仿函数,它接收类型列表以提取下一个类型,并且 std::tuple<Ts>
有一个 operator ()
来为每个 T 调用 doSomething<T>(args)
。
template<template<typename...> typename TL, typename... Ts>
struct someFunctor {
template<typename... Args>
static constexpr void operator() (Args&&... args) {
(doSomething<Ts>(std::forward<Args>(args)...), ...);
}
};
不确定这是否是最明智的方法。到目前为止,脑雾阻碍了我的工作。
使用模板偏特化提取类型列表的类型,然后使用fold-expression调用具有不同模板参数的doSomething
template<typename Tuple>
struct someFunctor;
template<typename... Args>
struct someFunctor<std::tuple<Args...>> {
template<class T>
constexpr void operator()(T&& x) {
(doSomething<Args>(std::forward<T>(x)), ...);
}
};
using types = std::tuple<int, char, float, double, w<int>, w<float>>;
constexpr auto data = std::make_tuple(1, 2, 3.0, 4.0f, w(5.0f));
someFunctor<types>()(data);
下面是一小段代码:
using types = std::tuple<int, char, float, double, w<int>, w<float>>;
constexpr auto data = std::make_tuple(1, 2, 3.0, 4.0f, w(5.0));
[&]<template<typename...> class TL, typename... Ts>(TL<Ts...>*) {
// Now have a parameter pack of `Ts`
(doSomething<Ts>(data), ...);
}((types*) nullptr);
并变成可重复使用的函数,你可以这样做:
template<typename types, typename Functor, typename... Args>
constexpr void mapTypeList(Functor&& f, Args&&... args) {
[&]<template<typename...> class TL, typename... Ts>(TL<Ts...>*) {
((void) f.template operator()<Ts>(std::forward<Args>(args)...), ...);
}(static_cast<types*>(nullptr));
}
// You need to wrap `doSomething` in a lambda
mapTypeList<types>([]<typename T>(const auto& data) { doSomething<T>(data); }, data);
// or maybe capturing data:
mapTypeList<types>([&]<typename T>() { doSomething<T>(data); });