[libcxx-commits] [libcxx] [libc++] Ensure that `std::expected` has no tail padding (PR #69673)
Jan Kokemüller via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Oct 27 10:09:52 PDT 2023
jiixyj wrote:
> * I moved all "union" and "repr" types out of the "expected" class.
>
> * Sadly, there is some code duplication going on since there are now _two_ repr classes instead of just one. :(
I managed to fix the code duplication by making `[[no_unique_address]]` conditional with `std::conditional`. So the current layout looks like this:
```c++
template <bool NoUnique, class Tp>
class conditional_no_unique_address {
struct unique {
Tp v;
};
struct no_unique {
[[no_unique_address]] Tp v;
};
public:
using type = std::conditional<NoUnique, no_unique, unique>::type;
}
// Returns true iff "has value" can be stuffed into the tail of the union.
template <class Union>
constexpr bool can_stuff_tail();
template <class Tp, class Err>
class expected_base {
union union_t {
[[no_unique_address]] Tp val;
[[no_unique_address]] Err unex;
};
struct repr {
private:
// If "has value" can be stuffed into the tail, this should be
// `[[no_unique_address]]`, otherwise not.
[[no_unique_address]] conditional_no_unique_address<
can_stuff_tail<union_t>(), union_t>::type union_;
[[no_unique_address]] bool has_val_;
};
protected:
// If "has value" can be stuffed into the tail, this must _not_ be
// `[[no_unique_address]]` so that we fill out the complete `expected` object.
[[no_unique_address]] conditional_no_unique_address<
!can_stuff_tail<union_t>(), repr>::type repr_;
};
template <class Tp, class Err>
class expected : private expected_base<Tp, Err> {};
```
https://github.com/llvm/llvm-project/pull/69673
More information about the libcxx-commits
mailing list