Although size() for std::initializer_list<T> can be evaluated as constexpr , the size() member will not behave like a constexpr inside the constexpr function: intentionally, the objects behave like constexpr in the constexpr expression where they were entered, but not elsewhere.
For example:
constexpr get_size(std::initializer_list<int> list) { constexpr std::size_t csize = list.size();
In the first case (1), the value assumed to be equal to a constexpr depends on the data created before the start of constexpr . As a result, he does not evaluate a constexpr . In the second case (2), the data is defined within constexpr , and thus, the result can become constexpr .
I did not participate in discussions leading to this design, but it seems to be motivated by the desire to prevent constexpr arguments that change the type of the result of the constexpr function: if the values โโwere constexpr inside the function definition, they would also be constexpr in the return value and could thus used as template arguments in the return type. This will lead to different values โโfor the constexpr function giving different types. Until now, you can get a different return type only by changing the types of the arguments to the function and / or by changing the number of arguments to the function.
Dietmar Kรผhl
source share