std-make
std-make copied to clipboard
expected (rev9): Omissions and mistakes
Under Section 1.6
-
template<class U, class G> explicit(see below) constexpr expected(const expected<U, G>& rhs)
: Are the constraints involvingE
andG
still applicable whenT
andU
are cvvoid
? -
template<class U, class G> explicit(see below) constexpr expected(expected<U, G>&& rhs)
: Are the constraints involvingE
andG
still applicable whenT
andU
are cvvoid
? -
template<class... Args> constexpr explicit expected(unexpect_t, Args&&... args);
: Should be "with the argumentsin_place, std::forward<Args>(args)....
" -
template<class U, class... Args> constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
: Should be "with the argumentsin_place, il, std::forward<Args>(args)....
"
Under Section 1.8
-
expected& operator=(const expected& rhs) noexcept(see below);
: noexcept specification does not match the one in the class synopsis. -
expected& operator=(expected&& rhs) noexcept(see below);
- Missing std::move, should be
move constructs an
unexpected_type<E> tmp
fromunexpected(std::move(this->error()))
(which can’t throw as E is nothrow-move-constructible)-
For
!bool(*this) && bool(rhs)
, missing "and sethas_val
totrue
" -
Constraint for when
T
is cv void should beis_move_constructible_v<E>
istrue
andis_move_assignable_v<E>
istrue
. -
Constraint for when
T
is not cv void should be (determined by following the logic in the table):is_move_constructible_v<T> && is_move_assignable_v<T> && is_move_constructible_v<E> && is_move_assignable_v<E> && (is_nothrow_move_constructible_v<E> || is_nothrow_move_constructible_v<T>)
-
The expression inside noexcept should be equivalent to:
is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<E> && is_nothrow_move_constructible_v<E>
-
template<class G = E> expected<T, E>& operator=(const unexpected<G>& e);
: Table is inverted -
expected<T, E>& operator=(const unexpected<G>& e);
andexpected<T, E>& operator=(unexpected<G>&& e);
-
Should be
e.value()
instead ofe.error()
. -
Temporary
unexpected<E>
should be created fromunexpected<G>
before destroyingval
to ensure strong exception guarantee.
-
-
expected<T, E>& operator=(unexpected<G>&& e);
, for!bool(*this)
: Missing std::move, should be "move assignunexpected(std::move(e).value())
to unex". -
template<class U = T> expected<T, E>& operator=(U&& v);
: Missing std::move, should be
move constructs an
unexpected<E> tmp
fromunexpected(std::move(this->error()))
(which can’t throw as E is nothrow-move-constructible)
-
Why are there no assignment operator overloads taking
expected<U, G>
? There are after all assignment operator overloads for std::optional takingstd::optional<U>
. -
template<class... Args> T& emplace(Args&&... args);
: By following the logic under Effects, the constraint should beis_constructible_v<T, Args...> && (is_nothrow_constructible_v<T, Args...> || is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E>)
. Upon exception, one or more arguments may be left in a post-moved state, so the "nothing changes" remark is not completely accurate. -
template<class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);
: By following the logic under Effects, the constraint should beis_constructible_v<T, L, Args...> && (is_nothrow_constructible_v<T, L, Args...> || is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E>)
whereL
isstd::initializer_list<U>
. Upon exception, one or more arguments may be left in a post-moved state, so the "nothing changes" remark is not completely accurate.
Under Section 1.9
-
Constraints should be
is_nothrow_move_constructible_v
, notis_move_constructible_v
. -
In table, for
bool(*this) && !bool(rhs)
and is cv void, should beunexpected(std::move(rhs.error()))
(missing.error()
)
Under Section 1.10
-
constexpr T&& expected::value() &&
andconstexpr const T&& expected::value() const&&
: Should they throwbad_expected_access(std::move(*this).error())
instead, in order to allow move-only error types? -
value_or
: Behavior and/or constraints need to be clarified whenT
isvoid
. Does it ignore the argument and do nothing, or is it disabled entirely?
Under Section 1.12
-
operator!=
: Should be "expression*x != v
is well-formed. -
operator!=
: Should be "Returns:bool(x) ? *x != v : true;
. Ifx
holds an error, than is it unequal to any valuev
. Otherwise,!( x != v)
would not be the same asx == v
.
Under Section 1.14
- Constraints don't match those for member swap.
Under Section 1.17.1
-
Should be
Err
in constraints, instead ofU
. -
template<class Err> constexpr explicit unexpected(Err&& e)
: Should beunexpect_t
in constraints, notunexpected
.