您的位置:首页 > 编程语言 > C语言/C++

C++14 make_index_sequence原理

2016-06-18 16:44 1241 查看

功能

    实现编译期的整数序列,如下例make_index_sequence<3>()会使fun函数的模板参数: int... N 推演为:0,1,2序列 :
#include <iostream>
#include <tuple>

using namespace std;

template<int... N>
decltype(auto) fun(index_sequence<N...> is) {
return make_tuple(N...);
}

int main() {

auto t = fun(make_index_sequence<3>());
cout << std::get<0>(t) << endl;
cout << std::get<1>(t) << endl;
cout << std::get<2>(t) << endl;
return 0;
}

实现分析

    傻瓜式实现

       即是生成一个可变的编译期整数序列,实际上目的就是要生成如下类的对象:
       
template<int...N>
struct index_sequence {};


      定义出上面的index_sequence后,其实就可以使用了,仍利用fun函数,调用方式为:

auto t = fun(index_sequence<0,1,2>());
     实际上就是一个空类,因为我们的目的只是模板的可变参数(英文直译应叫模板参数包),并生成一个递增的整数序列,这种实现实际什么都不需要做。

    更好的实现

       分析,c++14的实现的make_index_sequence模板只需指定一个模板参数 “N”,就会自动生成整数序列:0 - N-1,从接口来看:
       make_index_sequence<4> 可以实现为index_sequence的子类或,一个函数,并返回index_sequence<0,1,2...>对象。

       继承方式实现

        因c++14已定义index_sequence,为避免符号冲突,使用index_seq代替。
template<int... N>
struct index_seq{};

template<int N, int ...M>
struct make_index_seq: public make_index_seq<N - 1, N -1, M...> {

};

template<int ...M>
struct make_index_seq<0, M...> : public index_seq<M...> {
};
        实现的原理是,当给定一个整数N,如3,定义make_index_seq<3>() 对象时,模板可变参数M,由空逐渐推导为序列0,1,2。
       即make_index_seq<3> 时,M 为空。
           make_index_seq<3-1,3-1, M...>时,M 为3-1 = 2
           make_index_seq<2-1,2-1,M...>时,M为2-1=1,2 即序列(1,2)
           make_index_seq<1-1,1-1,M...>时,M为1-1 = 0, 1,2即序列(0,1,2)
           make_index_seq<0,M...>时,           M为(0,1,2)此时,make_index_seq<3>实际继承自index_seq<0,1,2>
      这样就生成了编译期的整数序列。

      对于使用函数方式还不知道是否可行,整体思路的代码如下:
template<int... M>
void make_index_seq_impl(std::true_type t) {

}

template<int N, int... M>
void make_index_seq_impl(std::false_type t) {

(N < 1) ? (make_index_seq_impl<M...>(std::true_type())) : (make_index_seq_impl<N-1, N-1, M...>(std::false_type()));
}
       此种写法是不可以的,会导编译器编译时,模板的无穷递归。

      
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: