[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
Sat Oct 21 05:22:26 PDT 2023
================
@@ -941,22 +897,90 @@ class expected {
std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
: __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+ template <class _Union>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
+ if (__has_val)
+ std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_);
+ else
+ std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
+ }
+
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
= default;
- // the expected's destructor handles this
+ // the __expected_repr's destructor handles this
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>)
{}
- _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
_LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_;
_LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
};
- _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_;
- bool __has_val_;
+ struct __expected_repr {
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr() = delete;
----------------
jiixyj wrote:
> What can certainly be removed from `__repr` and union constructors are the `std::__expected_construct_in_place_from_invoke_tag`/`std::__expected_construct_unexpected_from_invoke_tag` overloads. What do you think?
Well, that didn't work: It seems the function really has to be threaded down into the union and only `std::invoke`d down there...
```
# | In file included from /freebsd/data/linux/git-net/llvm-project/libcxx/test/std/utilities/expected/expected.expected/monadic/transform.pass.cpp:22:
# | In file included from /freebsd/data/linux/git-net/llvm-project/build/include/c++/v1/expected:44:
# | /freebsd/data/linux/git-net/llvm-project/build/include/c++/v1/__expected/expected.h:837:11: error: call to deleted constructor of 'NonCopy'
# | 837 | : __val_(std::forward<_Args>(__args)...) {}
# | | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | /freebsd/data/linux/git-net/llvm-project/build/include/c++/v1/__expected/expected.h:906:11: note: in instantiation of function template specialization 'std::expected<NonCopy, int>::__union
_t<NonCopy, int>::__union_t<NonCopy>' requested here
# | 906 | : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
# | | ^
# | /freebsd/data/linux/git-net/llvm-project/build/include/c++/v1/__expected/expected.h:173:9: note: in instantiation of function template specialization 'std::expected<NonCopy, int>::__repr::
__repr<NonCopy>' requested here
# | 173 | : __repr_(in_place, std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
# | | ^
# | /freebsd/data/linux/git-net/llvm-project/build/include/c++/v1/__expected/expected.h:703:14: note: in instantiation of function template specialization 'std::expected<NonCopy, int>::expecte
d<(lambda at /freebsd/data/linux/git-net/llvm-project/libcxx/test/std/utilities/expected/expected.expected/monadic/transform.pass.cpp:220:16) &, int &>' requested here
# | 703 | return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), __repr_.__union_.__val_);
```
https://github.com/llvm/llvm-project/pull/69673
More information about the libcxx-commits
mailing list