holomenicus
holomenicus

Reputation: 161

(How) can I cast between an aggregate type with one member and that member's type?

Is it possible to do this?

struct compound_type {
    int member;
};

void func()
{
    compound_type foo {384};
    int bar = sole_member_type_cast<int>(foo); // doesn't compile; there's no such thing
                                               // reinterpret_cast wouldn't compile here
    std::cout << bar << std::endl; // prints 384
}

I know it's possible with pointer aliasing, but it seems like this is a strict aliasing problem. (Is it?) Unions are also used, but again you aren't supposed to do so, as a union type "can hold only one of its non-static data members at a time" (ref).

In any case, would there be alignment or offset problems with this?

Upvotes: 0

Views: 270

Answers (2)

Artyer
Artyer

Reputation: 40881

A simple way to cast between a struct with one public non-static member and that member is to use a structured binding:

auto [bar] = foo;  // auto& to not copy
assert(bar == 384);

This works with non-standard-layout types too. For example, if compound_type::member was an int& or a std::vector<int>, &foo and &foo.member would no longer be pointer-interconvertible.

Upvotes: 2

cigien
cigien

Reputation: 60278

Yes, you can do:

int bar = *reinterpret_cast<int*>(&foo); 

This is well defined since objects of compound_type and int are pointer-inter-convertible. The address of foois the same as the address of its first data member which is an int, and so the reinterpret_cast is well defined.


As pointed out in the comments by @Remy Lebeau, the conversion could be simplified to:

int bar = reinterpret_cast<int&>(foo); 

which is much easier to read, and write.

Upvotes: 1

Related Questions