Given that std::array<T,N>::size
is constexpr, in the snippet below
Foo1::u
is not a static
member? The type is known at compile time and so is its size()
.Foo2::bigger()
?Listing:
// x86-64 gcc 10.1
// -O3 --std=c++20 -pedantic -Wall -Werror
#include <array>
#include <cstdint>
union MyUnion {
std::array<uint8_t,32> bytes;
std::array<uint32_t,8> words;
};
struct Foo1 {
MyUnion u;
static constexpr size_t length {u.bytes.size()};
//invalid use of non-static data member 'Foo1::u'
};
struct Foo2 {
MyUnion u;
size_t x;
consteval int8_t length() const { return u.bytes.size(); };
bool bigger() const { return x > length(); }
//'this' is not a constant expression
};
I would like to keep std::array length in MyUnion
declaration and not resort to
constexpr size_t LEN {32};
union MyUnion {
std::array<uint8_t,LEN> bytes;
std::array<uint32_t,LEN/4> words;
};
These situations are a bit different.
In the first one:
static constexpr size_t length {u.bytes.size()};
//invalid use of non-static data member 'Foo1::u'
You're trying to access a non-static data member without an object. That's just not a thing you can do. There needs to be some Foo1
associated with this expression. In the context of a non-static member function, it'd implicitly be this->u
, but there still needs to be some object there. There's only one exception: you're allowed to write sizeof(Foo1::u)
.
In the second one:
consteval int8_t length() const { return u.bytes.size(); };
Here, the this
pointer is not itself a constant expression (we don't know what it points to), so accessing anything through it fails. This is part of a broader case of constant expressions using unknown references in a way that doesn't really affect the constant-ness of the expression (see my blog post on the constexpr array size problem). I recently wrote a paper on this topic which was focused primarily on references, but this
is a narrow extension on top of that.
Either way, for now this can't work either, because everything has to be a constant. So you'll have to resort to something along the lines of what you suggest: expose the constant you want separately.