<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/129803>129803</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[libc++] `std::variant` introduces padding if a variant member contains a variant
</td>
</tr>
<tr>
<th>Labels</th>
<td>
libc++
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
zygoloid
</td>
</tr>
</table>
<pre>
[Testcase](https://godbolt.org/z/r7WEoEzTh):
```c++
#include <variant>
struct A {
int x;
};
struct B {
int y;
int z;
};
static_assert(sizeof(B) == 8);
static_assert(sizeof(std::variant<A, B>) == 12);
struct C {
std::variant<int> v;
};
static_assert(sizeof(C) == 8);
static_assert(sizeof(std::variant<A, C>) == 16);
```
`variant<A, C>` ought to be only 12 bytes, but is actually 16 bytes. The reason for this is that `std::variant` derives from `__sfinae_ctor_base<...>` and `__sfinae_assign_base<...>`, and those base classes are the *same* for `std::variant<A, C>` and for `std::variant<int>`.
This prevents the variant's first field (the `__union`) from being put at offset 0 within the variant, because that would mean we have two different `__sfinae_ctor_base<...>` subobjects at the same offset within the same object, and the C++ language rules don't permit that struct layout.
The solution is to change `variant` so that it doesn't derive from a class that is, or can be, independent of the `variant`'s template arguments. Perhaps either change the `__sfinae_...` types to use CRTP (even though they don't care what the derived class is), or remove them and rely on getting the special members' properties from the `__impl` type instead.
Of course, fixing this will break `std::variant`'s ABI, so it'd need to be done only in the unstable ABI. :(
`std::optional` appears to use the same implementation strategy, so I would imagine it has the same deficiency (assuming it puts the `T` first, not the `bool`), but I've not checked. And it looks like `std::tuple` may also suffer from the same issue.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJysVk1v2zgQ_TX0ZVBDpvx58MFxaqCnLRYB9hhQ4kjihiIFztCp8-sXpGS7SRughwUEJPJ8vXnzhqIiMq1D3IvVg1g9zlTkzof926X11hs9q7y-JNsTEteKUKwehdx2zAOJ8iDkSchT63XlLc99aIU8vQl5Cpt_vvqvb0-dkLvkVhzEuhifWsiH9BQHIUvjahs1giiPZxWMcizKr8lUHIhDrBkOIDbJGcA4hh-izJGbx-mfm9_DO7_LaB5f3j4EESs29bMiwsBCbsm8oW-E3D4IuQNRPoryEbYZ-a3GJxHEOrVXHm7ojwchj_CQ2rgnW8j32TLi4xXxb5KYTASc_xT58X9DfvyAfH3Pdp3gmFmsi9-Frgvwse0Y2EOF4J29wEJCdWGk5FRFBkOgao7KJtt6tM3hqUMIqMg7aHwA7gwlT-4Ug1gXvwBeF6AxmDMSNMH3yef5mRrjFD7X7MNzleRaHufz-QRMOf3Oa9T-L34JZnLlzhNCskJtE4MEKiBwhyDkgVSPQh4y1t_B-0BKSvi56zhvsS7mI7lPqfkh4BkdU6549ZUbgsYEYmgMWg1CbjOg1FZ0xrvcwG6kpELjWhgig2LwTUPIUMCr4c6491mPUGGtIuHI96uPVkOPysErQqfOCPzqQZumwYCO_4BsipWv_sWaKRVPxRJjVxQ_YRh_zq535hGO4zkBVrk2qhYhRIsE2jshNwwDht7wiHZaKKsuPvKNQQTyNrLxLsvIQ90p12aqfpIQ-TGHYdAeaUw-6mrkUI3Dn7yyhn2AWjmoML0Yp3FApxMrvoFpGPcKeWKM_WAVI6jQxj4NdQ7fMXRqIEDDHYYrutswJ3IToesC-DJgbiKN6Pj30_c0-CSPpNLYdinuciOnTjp97Sbex2701EdqYTd1EbD351yzz7wHtBfwDlpkTsrJ4xmwNspCj32FgYTcwBD8gIHNdfNumE0_2CtaMI4YlZ7m8VcDtY-BMmeN-TGmNwSvxlqoAqqXT7Y8E3h4-JYCyYNJO6DBIerpjNHeTQfNpKjoiFVlMUXNIX-mtrdD61bBD0kbKgNWw4Aq3Ai-yTI1hGleKuuIOCjG9jJB-TbtielVaxwmDXWK7tEaG1MbdPUlTUsRxT61bTitJF1pe0oA8kqntM7z1VB5b8dtvh6c34TcnDH71B3WL6jncHA6ZbTevxBY84LvaOQ4WEwFenUBZckDxbTD98GNfRJFnM_0vtS7cqdmuF9slotFKVe75azby2UjpV6sFztdrdV2UTVVtWzqYrusq-UW5czsZSFXRVksZblal8v5usFiJ1e62ayX9U7VYllgr4ydW3vu00VhlkvuF3K3LcqZVRVayncQKa2prpcEKdOdJOxT1JcqtiSWhTXEdM_Dhm2-vfwUtnr87IthHAevY40Eg9I6j6MBdT0IJ5VD7R0r4-humcVg9x-uPYa7WM1r3wt5SnimP1-G4MfT7JSbJCFPU5_nvfwvAAD__-d7ABc">