将元组类型转换为另一种元组类型
Transform tuple type to another tuple type
假设我有一个元组类型 std::tuple<x,y,z>
,或者 std::tuple<a,b>
。我想要一种通用的方法来转换我的元组中的类型,例如"functionize" 得到
std::tuple<std::function<void(x)>,
std::function<void(y)>,
std::function<void(z)>>
或者可能像
一样获得 shared_pointers 的存储空间
std::tuple<std::shared_pointer<a>,
std::shared_pointer<b>>
我如何使用 C++17 实现这一点? C++20 的答案很有趣,但不适用于我目前的情况。
动机:
我有一个 class 将由任意且不一定是唯一类型的列表参数化,并且希望列表中的每种类型都有一个 std::function 成员。
模板专业化可能是最简单的方法。
template <typename T>
struct functionize;
template <typename... Ts>
struct functionize<std::tuple<Ts...>> {
using type = std::tuple<std::function<void(Ts)>...>;
}
using MyTuple = std::tuple<int, double, char>;
using MyTupleFunctionized = typename functionize<MyTuple>::type;
为了使其更通用,您可以接受模板模板参数以应用于包。
template <typename Tuple, template <typename> typename Component>
struct transform_tuple;
template <typename... Ts, template <typename> typename Component>
struct transform_tuple<std::tuple<Ts...>, Component> {
using type = std::tuple<Component<Ts>...>;
}
using MyTuple = std::tuple<int, double, char>;
using MyTransformedTuple = typename transform_tuple<MyTuple, std::shared_ptr>::type;
更通用的解决方案最适用于 c++17
或更高版本。在此之前,它只会匹配具有 1 个参数的模板。在 c++17
之后,它也可以匹配 std::vector
之类的东西,它有 2 个模板参数,其中第二个有一个默认参数。
编辑:
正如@Jarod42 和@Caleth 在评论中指出的那样,我们可以对此进行更多改进。
template <typename Tuple, template <typename...> typename Component>
struct transform_tuple;
模板模板参数的参数包允许我们从 c++11
和转发中传递类似 std::vector
的内容。如果我们想传递混合类型和非类型参数的东西,比如 std::array
.
,那只会留下问题
我们可以通过使用模板别名部分解决这个问题。
template <typename T>
using FixedArray10 = std::array<T, 10>;
using MyTransformedTuple = typename transform_tuple<MyTuple, FixedArray10>::type;
假设我有一个元组类型 std::tuple<x,y,z>
,或者 std::tuple<a,b>
。我想要一种通用的方法来转换我的元组中的类型,例如"functionize" 得到
std::tuple<std::function<void(x)>,
std::function<void(y)>,
std::function<void(z)>>
或者可能像
一样获得 shared_pointers 的存储空间std::tuple<std::shared_pointer<a>,
std::shared_pointer<b>>
我如何使用 C++17 实现这一点? C++20 的答案很有趣,但不适用于我目前的情况。
动机: 我有一个 class 将由任意且不一定是唯一类型的列表参数化,并且希望列表中的每种类型都有一个 std::function 成员。
模板专业化可能是最简单的方法。
template <typename T>
struct functionize;
template <typename... Ts>
struct functionize<std::tuple<Ts...>> {
using type = std::tuple<std::function<void(Ts)>...>;
}
using MyTuple = std::tuple<int, double, char>;
using MyTupleFunctionized = typename functionize<MyTuple>::type;
为了使其更通用,您可以接受模板模板参数以应用于包。
template <typename Tuple, template <typename> typename Component>
struct transform_tuple;
template <typename... Ts, template <typename> typename Component>
struct transform_tuple<std::tuple<Ts...>, Component> {
using type = std::tuple<Component<Ts>...>;
}
using MyTuple = std::tuple<int, double, char>;
using MyTransformedTuple = typename transform_tuple<MyTuple, std::shared_ptr>::type;
更通用的解决方案最适用于 c++17
或更高版本。在此之前,它只会匹配具有 1 个参数的模板。在 c++17
之后,它也可以匹配 std::vector
之类的东西,它有 2 个模板参数,其中第二个有一个默认参数。
编辑:
正如@Jarod42 和@Caleth 在评论中指出的那样,我们可以对此进行更多改进。
template <typename Tuple, template <typename...> typename Component>
struct transform_tuple;
模板模板参数的参数包允许我们从 c++11
和转发中传递类似 std::vector
的内容。如果我们想传递混合类型和非类型参数的东西,比如 std::array
.
我们可以通过使用模板别名部分解决这个问题。
template <typename T>
using FixedArray10 = std::array<T, 10>;
using MyTransformedTuple = typename transform_tuple<MyTuple, FixedArray10>::type;