Initializing `constexpr` Array with Pattern

2019-05-21 06:36发布

问题:

I would like to initialize a constexpr array with a pattern that is generated using variadic template parameters. For simplicity, consider the problem of initializing a constexpr unsigned static array with the sizes of a list of types, say, unsigned, short, char, int, long. How can I do this so that all of the computation is done during compile time? I need the solution to play nice with the C++ type system, so I cannot use macros.

The best I could come up with is shown below, but compilation using g++ -std=c++11 -Wall -Ofast -S (using g++ 4.7) and inspection of the assembly clearly reveals that the values are pushed onto the stack during runtime. Any ideas? and works fine.

Using an array initializer as follows would work if I could somehow tell the expansion n +1 about expansion n.

static constexpr unsigned foo[] = { compute_element<Args>::value... };

Edit: Wait, never mind, I had a brainfart. The line above works fine...

Here is the code answer:

#include <iostream>

template <class... Args>
struct foo
{
    static constexpr unsigned bar[] = { sizeof(Args)... };
};

int main()
{
    std::cout << foo<unsigned, short, char, int, long>::bar[2] << std::endl;
    return 0;
}

Thank you very much for your time!

回答1:

Here is the answer. Keep in mind that due to limitations in C++, I think that this can only be done in-compile time to create arrays that are of the same size of the variadic template parameter pack.

#include <iostream>

template <class... Args>
struct foo
{
    static constexpr unsigned bar[] = { sizeof(Args)... };
};

int main()
{
    std::cout << foo<unsigned, short, char, int, long>::bar[2] << std::endl;
    return 0;
}