With the attribute [[no_unique_address]]
used for plain old data (POD) arrays like std::size_t[]
the template specialization for zero structure size could be as small as index
member is has, not occupying memory for the data
array.
When I do the same with the std::array
, this doesn’t work. Most likely because [[no_unique_address]]
it can’t handle compound object and this should have done in std::array
implementation itself, but as I guess it was developed before [[no_unique_address]]
attribute was introduced.
In case I need to have this std::array
directly in the structure (no pointers, references, etc.) is there a chance to make [[no_unique_address]]
working for std::array
as it does for std::size_t[]
?
Here is the demo
#include <array>
#include <iostream>
using data_type = std::size_t;
template<std::size_t _data_size>
struct ExtendableIndexArray
{
std::size_t index;
[[no_unique_address]] std::array<data_type, _data_size> data;
};
template<std::size_t _data_size>
struct ExtendableIndexPOD
{
std::size_t index;
[[no_unique_address]] data_type data[_data_size];
};
int main()
{
std::cout << "Sizeof std::size_t = " << sizeof(std::size_t) << "\n\n";
std::cout << "Sizeof ExtendableIndexPOD<0> = " << sizeof(ExtendableIndexPOD<0>) << '\n';
std::cout << "Sizeof ExtendableIndexPOD<1> = " << sizeof(ExtendableIndexPOD<1>) << '\n';
std::cout << '\n';
std::cout << "Sizeof ExtendableIndexArray<0> = " << sizeof(ExtendableIndexArray<0>) << '\n';
std::cout << "Sizeof ExtendableIndexArray<1> = " << sizeof(ExtendableIndexArray<1>) << '\n';
}
And the output:
Sizeof std::size_t = 8
Sizeof ExtendableIndexPOD<0> = 8
Sizeof ExtendableIndexPOD<1> = 16
Sizeof ExtendableIndexArray<0> = 16
Sizeof ExtendableIndexArray<1> = 16
It doesn't matter to [[no_unique_address]]
at all whether types are POD or not.
Also, std::array
is almost surely a POD type if the element type is one.
The problem here is that 1. a built-in array of size 0
is not permitted in C++. If the compiler permits instantiation of ExtendableIndexPOD<0>
without a diagnostic, then it is non-conforming to the ISO C++ standard (and neither to the ISO C standard). So arguing about the interaction with the ISO C++ feature [[no_unique_address]]
without talking about a specific compiler is pointless.
And 2. there is no guarantee that std::array
with size 0
as template parameter is implemented in such a way that the type will be empty (which is the only case in which [[no_unique_address]]
can help with layout optimization).
And lastly, [[no_unique_address]]
only permits the compiler to not give an empty object a unique address. Whether it will actually make that decision in order to reduce the size of the class is up to the compiler, or more specifically the ABI in use.