gpt4 book ai didi

c++ - 可变参数模板 : Interlacing multiple packs

转载 作者:可可西里 更新时间:2023-11-01 16:30:06 25 4
gpt4 key购买 nike

给定任意数量的包,从每包中取出第一种,将它们放在一起。然后从每个包中取出第二种,将它们放在一起,等等......然后将它们全部合并。任何剩下的人都会在他们之间重复这个过程。例如,为了更好的可读性,使用整数来表示不同的类型,

InterlacePacks<Pack<1 2 3 4>, Pack<5 6 7>, Pack<8 9 10 11 12>>::type

会给予

Pack<1 5 8 2 6 9 3 7 10 4 11 12>

仅当所有包的尺寸都相同 时,以下代码才有效。当包装尺寸不同时,我现在完全无法处理“剩菜”。到目前为止,这是我的代码。我会解释每个阶段,以便您了解我的计划:

#include <iostream>

// First a helper to remove the first N types from a pack:
template <int, typename> struct RemoveHead;

template <typename Pack>
struct RemoveHead<0, Pack> { using type = Pack; };

template <template <typename...> class P, typename First, typename... Rest>
struct RemoveHead<0, P<First, Rest...>> { using type = P<First, Rest...>; };

template <int N, template <typename...> class P, typename First, typename... Rest>
struct RemoveHead<N, P<First, Rest...>> : RemoveHead<N-1, P<Rest...>> {};

// Now a helper to merge multiple packs:
template <typename...> struct MergePacks;

template <typename Pack>
struct MergePacks<Pack> {
using type = Pack;
};

// Final Pack type shall be the first one listed, if there are different pack types.
template <template <typename...> class P1, template <typename...> class P2, typename... Types1, typename... Types2, typename... Packs>
struct MergePacks<P1<Types1...>, P2<Types2...>, Packs...> : MergePacks<P1<Types1..., Types2...>, Packs...> {};

// First collect the first type from each pack:
template <typename, typename...> struct InterlacePacksHelper1;

template <template <typename...> class P, typename... Ts>
struct InterlacePacksHelper1<P<Ts...>> { using type = P<Ts...>; };

template <template <typename...> class P, template <typename...> class FirstPack, typename... Ts, typename First, typename... Rest, typename... Packs>
struct InterlacePacksHelper1<P<Ts...>, FirstPack<First, Rest...>, Packs...> : InterlacePacksHelper1<P<Ts..., First>, Packs...> {};

// Now remove the first type from each pack and repeat the process. Use a parameter N as a counter, where N will start as the minimum size of the packs.
template <int, typename, typename...> struct InterlacePacksHelper;

template <template <typename...> class P, typename... Ts, typename... Packs>
struct InterlacePacksHelper<0, P<Ts...>, Packs...> { using type = P<Ts...>; };

template <int N, template <typename...> class P, typename... Ts, typename... Packs>
struct InterlacePacksHelper<N, P<Ts...>, Packs...> : InterlacePacksHelper<N-1,
typename MergePacks<P<Ts...>, typename InterlacePacksHelper1<P<>, Packs...>::type>::type,
typename RemoveHead<1, Packs>::type...> {};

// Now obtain the smallest pack size, given a list of packs.
template <int N, typename...> struct MinPackSize;

template <int N>
struct MinPackSize<N> : std::integral_constant<int, N> {};

template <int N, template <typename...> class P, typename... Types, typename... Packs>
struct MinPackSize<N, P<Types...>, Packs...> : std::integral_constant<int,
(sizeof...(Types) < N) ? sizeof...(Types) : N> {};

// Finally, InterlacePacks itself.
template <typename...> struct InterlacePacks;

template <template <typename...> class P, typename... Ts, typename... Packs>
struct InterlacePacks<P<Ts...>, Packs...> : InterlacePacksHelper<MinPackSize<sizeof...(Ts), Packs...>::value, P<>, P<Ts...>, Packs...> {};

// test ----------------------------------------------------------------
template <typename...> struct Pack {};
template <typename...> struct Group {};
template <typename...> struct Wrap {};
struct Object {}; struct Blob {};

int main() {
using TestPack1 = Pack<int, double, Object>; // 3 types
using TestPack2 = Group<double, std::string, int, short, long>; // 5 types
using TestPack3 = Wrap<char, short, Blob, std::string>; // 4 types
InterlacePacks<TestPack1, TestPack2, TestPack3>::type interlacedPack;
std::cout << std::boolalpha << std::is_same< decltype(interlacedPack),
Pack<int, double, char, double, std::string, short, Object, int, Blob> >::value << std::endl; // true
// Want it to be Pack<int, double, char, double, std::string, short, Object, int, Blob, short, std::string, long>
}

那么如何修改代码,使得想要的输出

Pack<int, double, char, double, std::string, short, Object, int, Blob, short, std::string, long>

结果呢?

注意:我尝试使用 MaxPackSize 代替 MinPackSize,但正如预期的那样无法编译。一种想法是在 MinPackSize 次迭代后丢弃空包并继续该过程,直到完成 MaxPackSize 次迭代(每次都移除新的空包)。不过这是理论上的(还没有尝试过):

template <typename, typename...> struct RemoveAllEmptyPacksHelper;

template <template <typename...> class P, typename... Packs>
struct RemoveAllEmptyPacksHelper<P<Packs...>> : Identity<P<Packs...>> {};

template <template <typename...> class P, typename... CurrentPacks, template <typename...> class FirstPack, typename... Types, typename... Packs>
struct RemoveAllEmptyPacksHelper<P<CurrentPacks...>, FirstPack<Types...>, Packs...> :
std::conditional<(sizeof...(Types) == 0),
RemoveAllEmptyPacksHelper<P<CurrentPacks...>, Packs...>,
RemoveAllEmptyPacksHelper<P<CurrentPacks..., FirstPack<Types...>>, Packs...>
>::type {};

template <typename> struct RemoveAllEmptyPacks;

template <template <typename...> class P, typename... Packs>
struct RemoveAllEmptyPacks<P<Packs...>> : RemoveAllEmptyPacksHelper<P<>, Packs...> {};

最佳答案

这是我迄今为止最短的 C++11 尝试:

template <class T, class...> struct interlace_ {using type = T;};
template <class... R, template<class...> class T, class f, class... t, class... P>
struct interlace_<std::tuple<R...>, T<f, t...>, P...>
: interlace_<std::tuple<R..., f>, P..., T<t...>> {};
template <class... R, template<class...> class T, class f, class... P>
struct interlace_<std::tuple<R...>, T<f>, P...>
: interlace_<std::tuple<R..., f>, P...> {};

template <class... packs>
using interlace = interlace_<std::tuple<>, packs...>;

Demo . P 代表包,R 是(当前)结果包,f 是第一个类型,t是当前观察到的包的尾部。 T 是保存包的模板。

关于c++ - 可变参数模板 : Interlacing multiple packs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28181962/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com