我在那里看到了示例代码,但我真的想要一步一步地解释如何对 index_sequence 进行编码以及每个阶段的元编程原则。
你问的问题并不容易解释......
嗯...std::index_sequence本身很简单:定义如下
template<std::size_t... Ints>
using index_sequence = std::integer_sequence<std::size_t, Ints...>;
实质上,它是无符号整数的模板容器。
棘手的部分是std::make_index_sequence 的实现。也就是说:棘手的部分是从std::make_index_sequence<N> 传递到std::index_sequence<0, 1, 2, ..., N-1>。
我建议你一个可能的实现(不是一个很好的实现,但简单(我希望)理解),我会尝试解释它是如何工作的。
不完全是从std::integer_sequence 传递的标准索引序列,但修复std::size_t 类型,您可以获得合理的indexSequence/makeIndexSequence 对,并使用以下代码。
// index sequence only
template <std::size_t ...>
struct indexSequence
{ };
template <std::size_t N, std::size_t ... Next>
struct indexSequenceHelper : public indexSequenceHelper<N-1U, N-1U, Next...>
{ };
template <std::size_t ... Next>
struct indexSequenceHelper<0U, Next ... >
{ using type = indexSequence<Next ... >; };
template <std::size_t N>
using makeIndexSequence = typename indexSequenceHelper<N>::type;
我认为了解其工作原理的一个好方法是遵循一个实际示例。
我们可以点对点地看到makeIndexSequence<3>如何变成index_sequenxe<0, 1, 2>。
我们将makeIndexSequence<3> 定义为typename indexSequenceHelper<3>::type [N 是3]
indexSequenceHelper<3> 仅匹配一般情况,因此从indexSequenceHelper<2, 2> 继承[N 为3 而Next... 为空]
indexSequenceHelper<2, 2> 仅匹配一般情况,因此从indexSequenceHelper<1, 1, 2> 继承 [N is 2 and Next... is 2]
indexSequenceHelper<1, 1, 2> 仅匹配一般情况,因此从 indexSequenceHelper<0, 0, 1, 2> 继承 [N is 1 and Next... is 1, 2]
indexSequenceHelper<0, 0, 1, 2> 匹配两种情况(一般为偏特化),因此应用偏特化并定义 type = indexSequence<0, 1, 2> [Next... 是 0, 1, 2]
结论:makeIndexSequence<3> 是indexSequence<0, 1, 2>。
希望这会有所帮助。
--- 编辑---
一些说明:
std::index_sequence 和 std::make_index_sequence 从 C++14 开始可用
我的示例很简单(我希望)可以理解,但是(正如 aschepler 所指出的)有很大的限制,即线性实现;我的意思是:如果你需要index_sequence<0, 1, ... 999>,使用makeIndexSequence<1000>,你以递归方式实现1000个不同的indexSequenceHelper;但是有一个递归限制(编译器形式编译器不同)可以小于 1000;还有其他算法会限制递归次数,但解释起来更复杂。