Getting a pointer to the contained object from std :: aligned_union_t

I want to build an object of arbitrary type inside with place-new std::aligned_union_t. After a successful build, I want to be able to return a pointer to the constructed object without saving it separately. Is it legal to do this just reinterpret_cast'in std::aligned_union_tif I guarantee that I applied it to the original type that was created?

Is the following code illustrating the above legal? Are there any type requirements that MyStructmust be met for this to be the case? For example, should it be a POD?

#include <type_traits>
#include <memory>
#include <cstddef>
#include <exception>

struct MyStruct
{
    int value = 0;
};

constexpr size_t c_alignedUnionSize = 10;
std::aligned_union_t<c_alignedUnionSize, std::max_align_t> g_storage;

MyStruct* GetPtr()
{
    return reinterpret_cast<MyStruct*>(std::addressof(g_storage));
}

void Construct()
{
    if (sizeof(MyStruct) > sizeof(g_storage))
    {
        std::terminate();
    }

    auto ptr = new (std::addressof(g_storage)) MyStruct{};
    if (!ptr)
    {
        std::terminate();
    }

    GetPtr()->value = 123;
}

void Destroy()
{
    GetPtr()->~MyStruct();
}

int GetValue()
{
    return GetPtr()->value;
}

int main()
{
    Construct();
    auto value = GetValue();
    Destroy();
    return value;
}
+4
source share
2 answers

reinterpret_castit should be safe here. The last standard project says:

[expr.reinterpret.cast]

. prvalue v " cv T", static_­cast<cv T*>(static_­cast<cv void*>(v)). [: " T1" " T2" ( T1 T2 T2 , T1) . - ]

:

+1

, . ++ reinterpret_cast a b , , , [basic.compound]/4:

a b , :

  • ,

  • one - , - ([class.union])

  • , , , ([class.mem])

  • c , a c - , c b .

, , reinterpret_­cast. [. , . - ]

, ( ), . :

alignas(int) unsigned char buff[2*sizeof(int)];
auto p1 = new(buff) int{};
auto p2 = new(buff+sizeof(int)) int{};
*(p1+1) = 10;//Undefined behavior
//p1+1 does not point to *p2 even if p1 and p2 have same type and value.

, , , new.


, , , ([expr.reinterpret_cast]/5):

reinterpret_cast<MyStruct*>(reinterpret_cast<std::uintptr_t>(addressof(g_storage));
+1

Source: https://habr.com/ru/post/1691516/


All Articles