Would it be possible to verify that an initializer list that is being passed to a constexpr
constructor is a certain size? Or would this only be possible to do at runtime?
This is the idea, but it doesn't work:
struct group
{
constexpr group(
std::initializer_list<std::initializer_list<UINT const> const> groups
)
{
static_assert(each_list_size_greater_than_1(groups.begin(), groups.end()));
}
constexpr static bool each_list_size_greater_than_1(
std::initializer_list<std::initializer_list<UINT const> const>::const_iterator const begin
, std::initializer_list<std::initializer_list<UINT const> const>::const_iterator const end)
{
return begin == end || begin->size() > 1 && each_list_size_greater_than_1(begin + 1, end);
}
};
I've looked at VS2015's std::initializer_list
implementation and begin()
, end()
and size()
are all constexpr
functions.
Although the size()
of an std::initializer_list<T>
can evaluate to a constexpr
the size()
member won't behave like a constexpr
within a constexpr
function: it is intentional that objects only behave like constexpr
within the constexpr
expression where they were introduce but not elsewhere.
For example:
constexpr get_size(std::initializer_list<int> list) {
constexpr std::size_t csize = list.size(); // ERROR (1)
std::size_t size = list.size(); // OK
return size;
}
int main() {
constexpr std::size_t csize = get_size(std::initializer_list<int>{ 1, 2, 3 }); // OK (2)
// ...
}
In the first case (1) the value which is assumed to yield a constexpr
depends on data created before the constexpr
starts. As a result, it doesn't evaluate to a constexpr
. In the second case (2) the data is defined within the constexpr
and, thus, the result can become a constexpr
.
I haven't been part of the discussions leading to this design but it seems it is motivated by the desire to prevent constexpr
arguments changing the result type of a constexpr
function: if the values were constexpr
s within the function definition, they would also be constexpr
s in the return value and could, thus, be used as template arguments in the return type. That would lead to different values to constexpr
function yielding different types. So far, you can get a different return type only by varying the argument types of a function and/or by changing the number of arguments of a function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With