Search code examples
c++castingunique-ptr

Casting std::unique_ptr<uint8_t[]> to struct unique_ptr without losing uint8_t[] buffer


Is there a way to cast a std::unique_ptr<uint8_t[]>(n) to std::unique_ptr</*some_struct*/> so that struct points to the same address as uint8_t ptr was as well as saving that buffer?

auto buffer = std::make_unique<uint8_t[]>(100);
std::unique_ptr<dummy> header = std::move(buffer); // error
struct dummy // string data
{
    uint64_t unk1; // 0x0

    uint64_t string_offset; // 0x8

    uint32_t c59d1c81; // 0x10

    uint16_t byte_length; // 0x14
    uint16_t string_length; // 0x16

    uint64_t unk2; // 0x18

    uint8_t* get_string() { return (uint8_t*)(uint64_t(this) + 0x8 + string_offset); }
};

In this example, buffer holds 0x20 bytes of dummy struct. However, it also contains a string which is obtainable by string_offset member and get_string method.


Solution

  • Ignoring possible aliasing/alignment issues, you might do

    auto buffer = std::make_unique<uint8_t[]>(100);
    std::unique_ptr<dummy, Deleter> header(reinterpret_cast<dummy*>(buffer.release()));
    

    With

    struct Deleter
    {
        void operator()(dummy* p) const {
            p->~dummy(); // Noop in your case
            delete[] reinterpret_cast<uint8*>(p);
        }
    };