天天看点

(C++模板编程):std::integer_sequence(下)std::integer_sequence

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;
           
  • 输出
(C++模板编程):std::integer_sequence(下)std::integer_sequence
【调用分析】
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;
           
  • 输出
(C++模板编程):std::integer_sequence(下)std::integer_sequence
【分析】
(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这种写法毫无问题。
           
【逻辑图】
(C++模板编程):std::integer_sequence(下)std::integer_sequence