__guard.release();
}
}
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3836. std::expected<bool, E1> conversion constructor
+ // expected(const expected<U, G>&) should take precedence over
+ // expected(U&&) with operator bool
+
+ // If T is cv bool, remove_cvref_t<U> is not a specialization of expected.
+ template<typename _Tp, typename _Up>
+ concept __not_constructing_bool_from_expected
+ = ! is_same_v<remove_cv_t<_Tp>, bool>
+ || ! __is_expected<remove_cvref_t<_Up>>;
}
/// @endcond
static_assert( ! __expected::__is_unexpected<remove_cv_t<_Tp>> );
static_assert( __expected::__can_be_unexpected<_Er> );
- template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
+ // If T is not cv bool, converts-from-any-cvref<T, expected<U, G>> and
+ // is_constructible<unexpected<E>, cv expected<U, G> ref-qual> are false.
+ template<typename _Up, typename _Gr, typename _Unex = unexpected<_Er>,
+ typename = remove_cv_t<_Tp>>
static constexpr bool __cons_from_expected
- = __or_v<is_constructible<_Tp, expected<_Up, _Err>&>,
- is_constructible<_Tp, expected<_Up, _Err>>,
- is_constructible<_Tp, const expected<_Up, _Err>&>,
- is_constructible<_Tp, const expected<_Up, _Err>>,
- is_convertible<expected<_Up, _Err>&, _Tp>,
- is_convertible<expected<_Up, _Err>, _Tp>,
- is_convertible<const expected<_Up, _Err>&, _Tp>,
- is_convertible<const expected<_Up, _Err>, _Tp>,
- is_constructible<_Unex, expected<_Up, _Err>&>,
- is_constructible<_Unex, expected<_Up, _Err>>,
- is_constructible<_Unex, const expected<_Up, _Err>&>,
- is_constructible<_Unex, const expected<_Up, _Err>>
+ = __or_v<is_constructible<_Tp, expected<_Up, _Gr>&>,
+ is_constructible<_Tp, expected<_Up, _Gr>>,
+ is_constructible<_Tp, const expected<_Up, _Gr>&>,
+ is_constructible<_Tp, const expected<_Up, _Gr>>,
+ is_convertible<expected<_Up, _Gr>&, _Tp>,
+ is_convertible<expected<_Up, _Gr>, _Tp>,
+ is_convertible<const expected<_Up, _Gr>&, _Tp>,
+ is_convertible<const expected<_Up, _Gr>, _Tp>,
+ is_constructible<_Unex, expected<_Up, _Gr>&>,
+ is_constructible<_Unex, expected<_Up, _Gr>>,
+ is_constructible<_Unex, const expected<_Up, _Gr>&>,
+ is_constructible<_Unex, const expected<_Up, _Gr>>
>;
- template<typename _Up, typename _Err>
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // If t is cv bool, we know it can be constructed from expected<U, G>,
+ // but we don't want to cause the expected(U&&) constructor to be used,
+ // so we only check the is_constructible<unexpected<E>, ...> cases.
+ template<typename _Up, typename _Gr, typename _Unex>
+ static constexpr bool __cons_from_expected<_Up, _Gr, _Unex, bool>
+ = __or_v<is_constructible<_Unex, expected<_Up, _Gr>&>,
+ is_constructible<_Unex, expected<_Up, _Gr>>,
+ is_constructible<_Unex, const expected<_Up, _Gr>&>,
+ is_constructible<_Unex, const expected<_Up, _Gr>>
+ >;
+
+ template<typename _Up, typename _Gr>
constexpr static bool __explicit_conv
= __or_v<__not_<is_convertible<_Up, _Tp>>,
- __not_<is_convertible<_Err, _Er>>
+ __not_<is_convertible<_Gr, _Er>>
>;
template<typename _Up>
template<typename _Up = _Tp>
requires (!is_same_v<remove_cvref_t<_Up>, expected>)
&& (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
- && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
&& is_constructible_v<_Tp, _Up>
+ && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
+ && __expected::__not_constructing_bool_from_expected<_Tp, _Up>
constexpr explicit(!is_convertible_v<_Up, _Tp>)
expected(_Up&& __v)
noexcept(is_nothrow_constructible_v<_Tp, _Up>)