I need to create constexpr array of bytes out of constexpr struct.
#include <array>
template<typename T>
constexpr std::array<uint8_t, sizeof(T)> o2ba(const T o) {
return {};
}
struct A {
int a;
};
int main() {
constexpr A x{ 1 };
constexpr auto y = o2ba(x); // y == { 0x01, 0x00, 0x00, 0x00 } for little endian
return 0;
}
I tried to extract it from union:
template<typename T>
union U {
T o;
std::array<uint8_t, sizeof(T)> d;
};
template<typename T>
constexpr std::array<uint8_t, sizeof(T)> o2ba(const T o) {
return U<T>{o}.d;
}
but it fails on both gcc and msvc compilers for accessing d instead of initialized o member. It works when initializing non constexpr object though, as below.
int main() {
constexpr A x{ 1 };
auto y = o2ba(x); // y == { 0x01, 0x00, 0x00, 0x00 } for little endian
return 0;
}
But that is not what I need. Is there a way to do this?
What you want is not possible. In your code, you try to access an initialized member in a constexpr
context, which is fine. The error is that you then try to access a non-active member, which isn't permitted per [expr.const#2.8]:
An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:
...
- an lvalue-to-rvalue conversion that is applied to a glvalue that refers to a non-active member of a union or a subobject thereof;
Now the alternative is to try to serialize the object to bytes the old fashion way, via reinterpret_cast
, i.e reinterpret_cast<const uint8_t*>(&a)
. Again reinterpret_cast
's aren't allowed allowed in a constexpr
context per 2.15 (same section). I suspect that the reason why you cannot do this is because it's unportable.
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