std::integer_sequence
【逆向排列数字生成一个类型Integer_Sequence_Reverse】
//向integer_sequence开头插入元素: //泛化版本 template<typename INTSEQ, unsigned int NewElem> //INTSEQ代表整个的std::integer_sequence< ......>类型 struct IntSeq_PushFront; //因为不使用泛化版本,所以泛化版本可以只声明不定义。 //向std::integer_sequence开头插入元素:特化版本 template<typename T, unsigned int... Elems, unsigned int NewElem> //泛化版本一般要求可变参放在最后,特化版本一般无此要求 struct IntSeq_PushFront< std::integer_sequence<T, Elems... >, NewElem > { using type = std::integer_sequence<T, NewElem,Elems... >; }; //----------------------------------- //泛化版本 template <typename T, unsigned int N,unsigned Count=1> //当N = 1调用特化版本,Count为常量1 struct Integer_Sequence_Reverse { using type = typename IntSeq_PushFront< typename Integer_Sequence_Reverse< T, N - 1 >::type, N - Count >::type; }; //特化版本 template <typename T,unsigned int N> struct Integer_Sequence_Reverse<T, N, N> { using type = std::integer_sequence<T, N-1>; }; //--------- //定义别名模板 template <typename T, unsigned int N> using Integer_Sequence_Reverse_T = typename Integer_Sequence_Reverse<T, N>::type; }
- 调用
Integer_Sequence_Reverse_T<int, 4> tmpobj4; cout << "tmpobj4的类型为:" << typeid(decltype(tmpobj4)).name() << endl;
- 输出
【调用分析】
Integer_Sequence_Reverse_T<int, 4> tmpobj4; //等价于 Integer_Sequence_Reverse<int, 4>::type tmpobj4; //把type看成函数调用 using type = IntSeq_PushFront<Integer_Sequence_Reverse< int,3>::type, 3 >::type; //展开上行后面这个Integer_Sequence_Reverse< int,3>::type如下 using type = IntSeq_PushFront<Integer_Sequence_Reverse< int,2>::type, 2 >::type; //展开上行后面这个Integer_Sequence_Reverse< int,2>::type如下 using type = IntSeq_PushFront<Integer_Sequence_Reverse< int,1>::type, 1 >::type; //展开上行后面这个Integer_Sequence_Reverse< int,1>::type,调用的是特化版本 using type = std::integer_sequence<int, 0>; //递归结束往回返 using type = std::integer_sequence<int, 1,0> using type = std::integer_sequence<int, 2,1,0> using type = std::integer_sequence<int,3,2,1,0> //最终结果 std::integer_sequence<int,3,2,1,0>
【将一个数字重复多次生成一个类型Repeat_Integer】
- 前面是通过递归调用的方式实现。现在这里通过递归继承的方式实现。
//泛化版本 template <std::size_t Num,std::size_t RepeatTime, typename INTSEQ = std::integer_sequence<std::size_t> > // INTSEQ代表整个的std::integer_sequence< ......>类型 class Repeat_Integer; //特化版本1: template <std::size_t Num, std::size_t RepeatTime, std::size_t... index > class Repeat_Integer<Num, RepeatTime, std::integer_sequence<std::size_t, index...> > : public Repeat_Integer<Num, RepeatTime - 1, std::integer_sequence<std::size_t, index..., Num>> { }; //特化版本2(用于结束递归) template <std::size_t Num, std::size_t... index > class Repeat_Integer<Num, 0, std::integer_sequence<std::size_t, index...> > { public: using type = std::integer_sequence<std::size_t, index...>; }; //定义别名模板 template <std::size_t Num, std::size_t RepeatTime> using Repeat_Integer_T = typename Repeat_Integer<Num, RepeatTime>::type;
- 调用
Repeat_Integer<1, 4>::type tmpobj5; cout << "tmpobj5的类型为:" << typeid(decltype(tmpobj5)).name() << endl; //希望显示的结果:struct std::integer_sequence<unsigned int,1,1,1,1> Repeat_Integer<1, 4, std::integer_sequence<std::size_t,12,18,19> >::type tmpobj6; cout << "tmpobj6的类型为:" << typeid(decltype(tmpobj6)).name() << endl;
- 输出
【分析】
(1)因为Repeat_Integer<1, 4>::type tmpobj5; 代码行的存在,导致系统会根据Repeat_Integer特化版本1实例化出如下类: Repeat_Integer<1, 4, std::integer_sequence<std::size_t>> (2)接着说tmpobj5,要想实例化出: Repeat_Integer<1, 4, std::integer_sequence<std::size_t>> 根据继承关系,编译器必须要实例化出他的父类,其实也就是: Repeat_Integer<Num, 3, std::integer_sequence<std::size_t, 1>> 上面这个写法注意:std::integer_sequence模板参数的末尾,已经多出个1了,而且此时的index代表的不在是0个参数,而是1个参数了。 ...... (3)在递归结束时,即 使用Repeat_Integer的特化版本2来实例化Repeat_Integer时,使用了using来定义类型别名type, 此时type就相当于类型std::integer_sequence<std::size_t, 1, 1, 1, 1>,因为是一种类继承关系,所以父类中定义的type在 子类中即可使用,因此Repeat_Integer<1, 4>::type这种写法毫无问题。
【逻辑图】