Is ptr to std::variant always == ptr to one of its alternatives?

Viewed 85

Stupid question but does this assumption always hold?

ptr to variant (class object) == ptr to variant alternative

Compare this, in which case it seems to be true:

#include <cstdio>
#include <variant>

using val = std::variant<std::monostate, int, bool, struct some_struct>;

struct some_struct
{
    void print_ptr() {
        printf("pointer to contents of variant A = %p\n", this);
    }
};

int main()
{
    val A = some_struct{};

    printf("pointer to variant A = %p\n", &A);
    std::get<some_struct>(A).print_ptr();
}

Yields

pointer to variant A = 0x7ffde4003818
pointer to contents of variant A = 0x7ffde4003818

But I can also imagine an implementation where the index variable is put before the union, which means that the union's address will start 1/2/4/8 bytes later.

1 Answers

There is an explicit requirement in the standard that standard layout unions and structs have the same address as the address of their first member (for unions, the same as all members). There is no such requirement for variants. Indeed, the only requirement on the layout of a variant is that the storage for the T that currently exists in the variant cannot be outside of the variant in dynamic memory.

That's it. As such, this behavior is entirely implementation-dependent. It can change from standard library to standard library. It can even change depending on which Ts you use in the variant.

It is not reliable.

Also not reliable is the assumption that all of the alternatives have the same address. The standard imposes no such requirement on variant.

Related