简体   繁体   中英

How does integer_sequence get unfolded to generate a sequence?

I have this code that generates an compile-time array of 1 to 10

template <int... Is> // when called below, Is will be 0 - N
constexpr std::array<int, sizeof...(Is)>
make_inc_array_impl(std::integer_sequence<int, Is...>) {
    return {{(Is + 1)...}}; // +1 to start at one instead of [0, 1, ...]
}

template <std::size_t N>
constexpr std::array<int, N> make_inc_array() {
    return make_inc_array_impl(std::make_integer_sequence<int, N>{});
}

constexpr auto a = make_inc_array<10>(); // [1, 2, ..., 10]

int main() {
    for(int itr = 0; itr < 10; ++itr)
        printf("%d ", a[itr]);
}

Well, I've got some experience and knowledge of how meta-programming works. But still I don't get how this amazing example really works.

  1. From the make_inc_array_impl() , I see that, it returns (Is+1)... So should the result be [11, 10, 9, 8, 7, ... 2] since Is value starts from 10 ?

  2. How is the variadic template function make_integer_sequence(parameter pack) unfolds/expands the std::integer_sequence<int, Is...> ? In a normal meta-programming, template deduction works recursively from N to N-1 , down to 1 . But here why it results from 1 to N ?

Could you help to explain what the principle behind?

The call to make_inc_array<10>() returns make_inc_array_impl(std::make_integer_sequence<int, 10>{}) . std::make_integer_sequence is an alias template. In particular, it's implemented so that std::make_integer_sequence<int, 10> is an alias for the type std::integer_sequence<int, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9> . Thus, when make_inc_array_impl is called with an argument of this type, Is... gets deduced to 0 1 2 3 4 5 6 7 8 9 in order to make the parameter type std::integer_sequence<int, Is...> equal to the argument type. Finally, this pack is expanded in the body of make_inc_array_impl . The pack expansion is guaranteed to occur in order, so it becomes 0 + 1 , 1 + 1 , ..., 9 + 1 .

The most tricky part of this is std::make_integer_sequence . How does it expand to an std::integer_sequence specialization with the actual consecutive integers desired? Well, this was inserted into the standard library so that you don't have to remember how to do it yourself, but if you want to see the answer, look here .

You generally need a helper function which is invoked with the result of std::make_integer_sequence<int, N>{} so that there is a place to put the individual integers in the sequence, ie, the pack Is... . Now that you're aware of this trick, you'll start seeing many places where you can use it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM