C++模板 index_sequence使用示例详解
作者:amjieker
引言
integer_sequence
是 c++ 14中新增加的一个元编程工具
其衍生出来的还有如 index_sequence
、make_index_sequence
、index_sequence_for
等辅助工具
现在,让我们来浅尝一下这些东西吧!
integer_sequence
integer_sequence
其实没有什么特殊的,就是一个类
只不过他是index_sequence
的基础
template<typename _Tp, _Tp... _Idx> struct integer_sequence { typedef _Tp value_type; static constexpr size_t size() noexcept { return sizeof...(_Idx); } };
index_sequence
index_sequence
会在编译期生成一个从0开始的序列
然后你就可以对其进行一些奇奇怪怪的操作
template <size_t... N> void print(std::index_sequence<N...>) { std::vector<int> res; (void)std::initializer_list<int>{ ((res.push_back(N), std::cout << N << " "), 0)...}; std::for_each(res.begin(), res.end(), [](int x) {std::cout << x << " ";}); } int main() { auto t = std::make_index_sequence<10>(); print(t); return 0; }
比如 ((res.push_back(N), std::cout << N << " "), 0)...
这句话,就会在编译期被展开
这里展开在了一个初始化列表中,小技巧
make_index_sequence
那么,index_sequence 是如何生成的呢?
有两种形式
- 编译器内建
- 递归式的生成
第二种方式嘛还是用到了元编程的惯用伎俩,特化,递归式的编程
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...> {};
对齐使用也是一样的形式
template <int... N> void print(index_seq<N...>) { (void)std::initializer_list<int>{((std::cout << N << " "), 0)...}; } int main() { auto r = make_index_seq<100>(); print(r); return 0; }
使用场景
刚才,看见了print去打印的时候打印了 0-(N-1)的元素
那么,这个行为是在编译期展开的,我们就可以用到其他需要常量的地方
比如一个简单的需求:
打印tuple
!
template <typename T, typename F, int...N> void exec_for_tuple(const T& tup, F&& func, index_seq<N...>) { (void)std::initializer_list<int> { (func(std::get<N>(tup)), 0)... }; } template <typename Func, typename ...Arg> void for_tuple(Func&& func, std::tuple<Arg...> tuple) { exec_for_tuple(tuple, std::forward<Func>(func), make_index_seq<sizeof...(Arg)>()); }
exec_for_tuple
部分应该非常好懂,但是为什么中间还要再转发一层呢?
因为tuple
元素的个数我们不能直接获取到,我们写的又要是一个通用的函数
所以要通过 sizeof...(arg)
这种伎俩来将其元素个数计算出来
如何调用呢?
如下所示:
std::tuple<int, int, double> tuple{1, 2, 3.0}; for_tuple([](auto t) { std::cout << t << " "; }, tuple);
index_sequence_for
那么,看到现在,你知道 index_sequence_for
又是何物吗?
其实吧,刚才就已经见过 index_sequence_for
这个东西了
其实就是计算可变长模板参数的个数,然后将其长度做成一个sequence出来
template<typename... _Types> using index_sequence_for = make_index_seq<sizeof...(_Types)>;
结语
index_sequence
是一个不起眼的家伙,可能你平时都不会去了解它,但是这个东西的用途还是有很多的,你想想,编译器制造一串序列的能力,在tuple这种模板中,使用其是不是更加方便了,在bind这种模板中的参数上,若是使用它,是不是更加灵活好些了。
其实和tuple一个道理,在平常编程中,你也许不会使用它,但是在模板编程中,这是比较好的一个工具。
以上就是C++模板 index_sequence使用示例详解的详细内容,更多关于C++模板index_sequence的资料请关注脚本之家其它相关文章!