std::make_integer_sequence究竟是如何实现的
How exactly is std::make_integer_sequence implemented?
我正在观看C++11/14元编程讲座,其中描述了常见算法和tmp模式的一些有效替代方案。
大部分效率增益来自使用可变参数模板而不是递归遍历,在许多情况下,使用可变参数模板的方法是扩展通过索引技巧或其他std::integer_sequence
即时技巧生成的可变参数包。
由于这种效率来自于这样一个事实,即实例化std::integer_sequence
,特别是别名std::make_integer_sequence
并不是一项昂贵的任务,我想确保当前最先进的C++1y标准库实现足够高效,可以使make_integer_sequence
即时化不是一项复杂且耗时/内存的任务。std::make_integer_sequence
在 C++1y 就绪编译器中实际实现的究竟是如何实现的?
,而是在问编译器供应商实际上如何决定实现它。
据我所知,make_sequence
的唯一实现是简单的 O(n( 递归方法和聪明的 O(logN( 分而治之。
目前没有一个主要的编译器标准库提供 N3658 编译时整数序列的子 O(n((对数或其他(实现。
libstdc++ (gcc(:
标准 O(n( 实现遍历typedef
链。这相当于连接到递归调用返回的列表末尾的 FP 函数。
libc++ (clang(:
O(n( 实现,但有一个有趣的 8 倍展开循环。
MSVC (VS14 CTP1(:
O(n(,使用在整数常量和整数序列上模板化的递归继承,后者用作累加器(在FP意义上(。(请注意,VS14 实现实际上位于 type_traits
标头中,而不是utility
中。
ICC 当前未记录为提供编译时整数常量支持。
在这一点上,担心std::integer_sequence
的效率可能不值得;编译时整数序列适合的任何问题都会在所用算法的 big-O 性能影响编译时间之前很久就遇到编译器的限制(在函数和模板参数的数量等方面(。还要考虑的是,如果std::make_integer_sequence
在编译中的其他任何地方使用(例如在库模板代码中(,那么编译器将能够重用该调用,因为模板元编程是纯粹的功能。
6+ 年后,编译器支持内置功能来快速完成此操作。Clang和MSVC有__make_integer_seq
.海湾合作委员会有__integer_pack
.事实上,STL 实现假设存在这样的内置!在这三个编译器之间,似乎只有 clang 的/libc++ 具有make_integer_sequence
的回退实现。
GCC 手册的C++扩展:类型特征部分通过以下方式描述了__integer_pack
:
__integer_pack(长度(
当用作模板定义中的包扩展模式时,将扩展到包含从 0 到 length-1 的整数的模板参数包。这是为了有效实施 std::make_integer_sequence 而提供的。
我在 clang 手册中没有找到描述__make_integer_seq
的部分,但是有对将其添加到 clang 的提交的评论。
在与我的GCC 11.1.0副本一起安装的libstdcxx中,这是<utility>
(第328行(中的代码,用于make_integer_sequence
:
/// Alias template make_integer_sequence
template<typename _Tp, _Tp _Num>
using make_integer_sequence
#if __has_builtin(__make_integer_seq)
= __make_integer_seq<integer_sequence, _Tp, _Num>;
#else
= integer_sequence<_Tp, __integer_pack(_Num)...>;
#endif
同样,Microsoft的STL在第34行<type_traits>
中对此进行了定义:
template <class _Ty, _Ty _Size>
using make_integer_sequence = __make_integer_seq<integer_sequence, _Ty, _Size>;
最后,从第 39 行开始libcxx/include/__utility/integer_sequence.h
有一个预处理器条件来检查我们是否需要使用回退:
#if __has_builtin(__make_integer_seq) && !defined(_LIBCPP_TESTING_FALLBACK_MAKE_INTEGER_SEQUENCE)
template <class _Tp, _Tp _Ep>
using __make_integer_sequence _LIBCPP_NODEBUG = __make_integer_seq<integer_sequence, _Tp, _Ep>;
#else
// fallback implementation that uses recursive templates
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为左值和右值的包装器实现C++范围
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 使用GSoap实现ONVIF
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 用于AVX的ln(x)的实现,m256
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 如何实现内部实现依赖于模板参数的类
- 我的 PRNG 实现与我尝试复制的实现有何不同?