c++ - 生成模板包

标签 c++ templates c++11 variadic

Generate<P<3>, P<5,0>, P<4,0,0>, P<3,0,1>>::type是要

Pack< A<0>, A<0,0>, A<0,0,0>, A<0,0,1>, A<0,0,2>, A<0,0,3>, A<0,1>, A<0,1,0>, A<0,1,1>, A<0,1,2>, A<0,2>, A<0,3>, A<0,4>, A<1>, A<2> >

因为P<3>意味着 P<n>对于 n = 0,1,2 存在; P<5,0>意味着 A<0,n>对于 n = 0,1,2,3,4 存在; P<4,0,0>意味着 A<0,0,n>对于 n = 0,1,2,3 存在;和 P<3,0,1>意味着 A<0,1,n>对于 n = 0,1,2 存在。 在订购方面,A<n1,n2,n3,...,nk,x,...>将始终在 A<n1,n2,n3,...,nk,y,...> 之前如果 x < y 和 A<n1,n2,n3,...,nk>将始终在 A<n1,n2,n3,...,nk, ...> 之前,其中第二个省略号 ... 是非空的。 所以我需要写出 Generate<Packs...> 的实现.

这样做的动机:如果template <int... Is> class ObjectIs...有一定的可能性pack,由上面的 3、5、4 和 3 等常量定义,那么所有可能类型的包将允许 代具体Object<Is...>通过包迭代实例。

这是我目前所拥有的:

#include <iostream>
#include <type_traits>

template <int...> class A;
template <typename...> struct Pack;
template <int...> struct P;

template <int N, int Count, typename Front, typename Output> struct GenerateHelper;

template <int N, int Count, int... Is, typename... As>
struct GenerateHelper<N, Count, P<Is...>, Pack<As...>> :
    GenerateHelper<N, Count + 1, P<Is...>, Pack<As..., A<Is..., Count>>> {};

template <int N, int... Is, typename... As>
struct GenerateHelper<N, N, P<Is...>, Pack<As...>> {
    using type = Pack<As...>;
};

template <typename...> struct Generate;

// Simple special case just to start off.  Generate has only one pack to deal with.
template <int N, int... Is>
struct Generate<P<N, Is...>> : GenerateHelper<N, 0, P<Is...>, Pack<>> {};

int main() {
    using T = Generate<P<3,0,0>>::type;
    std::cout << std::is_same<T, Pack<A<0,0,0>, A<0,0,1>, A<0,0,2>>>::value << '\n'; // true
}

但现在我对 Generate 中只有 2 包的情况感到困惑。谁能帮我继续?

思路:2个包,单独生成,合并两个Pack s,然后排序?但我认为排序将是最难的部分。

最佳答案

诀窍是意识到您从每个“生成”过程中获得的序列已经排序,并且问题减少到合并几个排序列表。

为简单起见,我制作了APackP 空结构。

template <int...> class A {};
template <typename...> struct Pack {};
template <int...> struct P {};

从一个P生成一组A:

template<int I, int... Tail>
auto do_sequence_for(P<I, Tail...>) -> std::make_integer_sequence<int, I>;

template<class PP>
using sequence_for = decltype(do_sequence_for(PP()));

template<int I, int... Front, int... Tail>
auto do_generate_single(P<I, Front...>, std::integer_sequence<int, Tail...>)
     -> Pack<A<Front..., Tail>...>;

template<class PP>
using generate_single = decltype(do_generate_single(PP(), sequence_for<PP>()));

两个A的字典顺序比较:

template<class A1, class A2>
struct compare; // returns A1 < A2

template<int I, int J, int...Is, int...Js>
struct compare<A<I, Is...>, A<J, Js...>> : std::integral_constant<bool, I < J> {};

template<int I, int...Is, int...Js>
struct compare<A<I, Is...>, A<I, Js...>> : compare<A<Is...>, A<Js...>> {};

template<int...Is>
struct compare<A<Is...>, A<>> : std::false_type {};

template<int J, int...Js>
struct compare<A<>, A<J, Js...>> : std::true_type {};

合并两个已排序的 A 包:

template<class Pack1, class Pack2, class Result=Pack<>>
struct merge2;

template<class A1, class...A1s, class A2, class...A2s, class...R>
struct merge2<Pack<A1, A1s...>, Pack<A2, A2s...>, Pack<R...>>
    : std::conditional_t<compare<A1, A2>::value,
                         merge2<Pack<A1s...>, Pack<A2, A2s...>, Pack<R..., A1>>,
                         merge2<Pack<A1, A1s...>, Pack<A2s...>, Pack<R..., A2>>>
{};

template<class...A1s, class...R>
struct merge2<Pack<A1s...>, Pack<>, Pack<R...>>
{
    using type = Pack<R..., A1s...>;
};

template<class A2, class...A2s, class...R>
struct merge2<Pack<>, Pack<A2, A2s...>, Pack<R...>>
{
    using type = Pack<R..., A2, A2s...>;
};

合并许多已排序的 A 包:

template<class... Packs>
struct merge;

template<class P1>
struct merge<P1> {
    using type = P1;
};

template<class P1, class P2, class... Ps>
struct merge<P1, P2, Ps...> : merge<typename merge2<P1, P2>::type, Ps...> {};

综合考虑:

template<class...Ps>
struct Generate{
    using type = typename merge<generate_single<Ps>...>::type;
};

Demo .

关于c++ - 生成模板包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32409666/

相关文章:

javascript - Angular 1.5 通过使用另一个组件返回函数中的 html 结果

c++ - 基于不同枚举值的类成员重载(或特化)

c++ - 最常见的字母子串

c++ - 为什么Rcout和Rprintf在多线程时会导致堆栈限制错误?

c++ - 在 Qt 中将 T 的集合转换为 QVariant 的集合

c++ - 检查类是否有函数(返回类型和 const 检查)

c - 在 Erlang C NIF 中操作二进制文件

c++ - 编写内存安全的 C++ 应用程序需要什么?

c++ - 使用 CPLEX (c++) 重置目标函数

区分枚举类和常规枚举的 C++11 类型特征