I would like to be explicit about array size restrictions on a member variable, to stop others from accidentally making silly changes. The following naive attempt will not compile:
struct Foo
{
std::array< int, 1024 > some_array;
static_assert( (some_array.size() % 256) == 0, "Size must be multiple of 256" );
//^ (clang) error: invalid use of non-static data member 'some_array'
};
Even though std::array::size
is a constexpr, I can't directly use static_assert
like that because neither the function nor my member variable is static.
The solution I came up with is to use decltype
(since I don't want to typedef the array) as follows:
static_assert( (decltype(some_array)().size() % 256) == 0, "Size must be multiple of 256" );
This looks like it's default-constructing an rvalue, which I didn't think is a constexpr.
Why does this work?
Is there a cleaner way to achieve the static assertion?
because neither the function nor my member variable is static.
Right. The problem is that the static assert can't refer to a non-static member, because some_array.size()
is equivalent to this->some_array.size()
and there is no this
pointer at class scope (only inside function declarators and default member initializers).
However, it is OK to say decltype(array_size)
because that isn't actually trying to refer to the object array_size
or invoke its member functions, it's just querying the type of a name declared in the class.
This looks like it's default-constructing an rvalue, which I didn't think is a constexpr.
array<int, N>
is a literal type, so can be constructed in constant expressions. The fact you're constructing an rvalue doesn't matter, you can construct a literal type and call a constexpr member function on it in a constant expression.
Something like array<std::string, N>
could not be used there, because std::string
is not a literal type, and so neither is array<string, N>
.
Is there a cleaner way to achieve the static assertion?
The standard trait std::tuple_size
is specialized for std::array
so you can do:
static_assert( std::tuple_size<decltype(some_array)>::value % 256) == 0,
"Size must be multiple of 256" );
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