Is it possible to use [[no_unique_address]] with non-POD types?

77 Views Asked by At

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
1

There are 1 best solutions below

8
On BEST ANSWER

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.