PR libstdc++/90165 constrain variant(T&&) constructor
Also refactor some constraints slightly to be more readable. PR libstdc++/90165 * include/std/variant (variant::__not_self): New helper for the is_same_v<remove_cvref_t<T>, variant>==false constraints. (variant::__to_type_impl): Remove. (variant::__to_type): Add default argument to check pack size, instead of using __to_type_impl. (variant::__accepted_type): Add default argument using __not_self. (variant::__is_in_place_tag, variant::__not_in_place_tag): New helpers for variant(T&&) constructor constraint. (variant::variant(T&&)): Use __not_in_place_tag in constraints. Extract __accepted_type into a named template parameter for reuse in other constraints and in the exception specification. (variant::variant(in_place_type_t<T>, Args&&...)) (variant::variant(in_place_type_t<T>, initializer_list<U>, Args&&...)) (variant::variant(in_place_index_t<T>, Args&&...)) (variant::variant(in_place_index_t<T>, initializer_list<U>, Args&&...)) (variant::operator=T&&)): Remove redundant && from trait arguments. * testsuite/20_util/variant/compile.cc: Check variant(T&&) constructor isn't used for in_place_type or in_place_index arguments. From-SVN: r270509
This commit is contained in:
parent
82e8c3da74
commit
06715e1cfb
|
@ -1,5 +1,25 @@
|
|||
2019-04-23 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/90165
|
||||
* include/std/variant (variant::__not_self): New helper for the
|
||||
is_same_v<remove_cvref_t<T>, variant>==false constraints.
|
||||
(variant::__to_type_impl): Remove.
|
||||
(variant::__to_type): Add default argument to check pack size, instead
|
||||
of using __to_type_impl.
|
||||
(variant::__accepted_type): Add default argument using __not_self.
|
||||
(variant::__is_in_place_tag, variant::__not_in_place_tag): New helpers
|
||||
for variant(T&&) constructor constraint.
|
||||
(variant::variant(T&&)): Use __not_in_place_tag in constraints.
|
||||
Extract __accepted_type into a named template parameter for reuse in
|
||||
other constraints and in the exception specification.
|
||||
(variant::variant(in_place_type_t<T>, Args&&...))
|
||||
(variant::variant(in_place_type_t<T>, initializer_list<U>, Args&&...))
|
||||
(variant::variant(in_place_index_t<T>, Args&&...))
|
||||
(variant::variant(in_place_index_t<T>, initializer_list<U>, Args&&...))
|
||||
(variant::operator=T&&)): Remove redundant && from trait arguments.
|
||||
* testsuite/20_util/variant/compile.cc: Check variant(T&&) constructor
|
||||
isn't used for in_place_type or in_place_index arguments.
|
||||
|
||||
* include/std/type_traits (unwrap_reference_t): Define for C++2a.
|
||||
(unwrap_ref_decay): Remove inheritance from unwrap_reference.
|
||||
* testsuite/20_util/unwrap_reference/1.cc: Adjust test to use alias.
|
||||
|
|
|
@ -1284,6 +1284,10 @@ namespace __variant
|
|||
__detail::__variant::_Traits<_Types...>::_S_default_ctor,
|
||||
variant<_Types...>>;
|
||||
|
||||
template<typename _Tp>
|
||||
static constexpr bool __not_self
|
||||
= !is_same_v<__remove_cvref_t<_Tp>, variant>;
|
||||
|
||||
template<typename _Tp>
|
||||
static constexpr bool
|
||||
__exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>;
|
||||
|
@ -1292,17 +1296,10 @@ namespace __variant
|
|||
static constexpr size_t __accepted_index =
|
||||
__detail::__variant::__accepted_index<_Tp&&, variant>::value;
|
||||
|
||||
template<size_t _Np, bool = _Np < sizeof...(_Types)>
|
||||
struct __to_type_impl;
|
||||
template<size_t _Np, typename = enable_if_t<(_Np < sizeof...(_Types))>>
|
||||
using __to_type = variant_alternative_t<_Np, variant>;
|
||||
|
||||
template<size_t _Np>
|
||||
struct __to_type_impl<_Np, true>
|
||||
{ using type = variant_alternative_t<_Np, variant>; };
|
||||
|
||||
template<size_t _Np>
|
||||
using __to_type = typename __to_type_impl<_Np>::type;
|
||||
|
||||
template<typename _Tp>
|
||||
template<typename _Tp, typename = enable_if_t<__not_self<_Tp>>>
|
||||
using __accepted_type = __to_type<__accepted_index<_Tp>>;
|
||||
|
||||
template<typename _Tp>
|
||||
|
@ -1311,6 +1308,17 @@ namespace __variant
|
|||
|
||||
using _Traits = __detail::__variant::_Traits<_Types...>;
|
||||
|
||||
template<typename _Tp>
|
||||
struct __is_in_place_tag : false_type { };
|
||||
template<typename _Tp>
|
||||
struct __is_in_place_tag<in_place_type_t<_Tp>> : true_type { };
|
||||
template<size_t _Np>
|
||||
struct __is_in_place_tag<in_place_index_t<_Np>> : true_type { };
|
||||
|
||||
template<typename _Tp>
|
||||
static constexpr bool __not_in_place_tag
|
||||
= !__is_in_place_tag<__remove_cvref_t<_Tp>>::value;
|
||||
|
||||
public:
|
||||
variant() = default;
|
||||
variant(const variant& __rhs) = default;
|
||||
|
@ -1320,20 +1328,21 @@ namespace __variant
|
|||
~variant() = default;
|
||||
|
||||
template<typename _Tp,
|
||||
typename = enable_if_t<!is_same_v<decay_t<_Tp>, variant>>,
|
||||
typename = enable_if_t<(sizeof...(_Types)>0)>,
|
||||
typename = enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
|
||||
&& is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>>>
|
||||
typename = enable_if_t<sizeof...(_Types) != 0>,
|
||||
typename = enable_if_t<__not_in_place_tag<_Tp>>,
|
||||
typename _Tj = __accepted_type<_Tp&&>,
|
||||
typename = enable_if_t<__exactly_once<_Tj>
|
||||
&& is_constructible_v<_Tj, _Tp>>>
|
||||
constexpr
|
||||
variant(_Tp&& __t)
|
||||
noexcept(is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
|
||||
noexcept(is_nothrow_constructible_v<_Tj, _Tp>)
|
||||
: variant(in_place_index<__accepted_index<_Tp&&>>,
|
||||
std::forward<_Tp>(__t))
|
||||
{ }
|
||||
|
||||
template<typename _Tp, typename... _Args,
|
||||
typename = enable_if_t<__exactly_once<_Tp>
|
||||
&& is_constructible_v<_Tp, _Args&&...>>>
|
||||
&& is_constructible_v<_Tp, _Args...>>>
|
||||
constexpr explicit
|
||||
variant(in_place_type_t<_Tp>, _Args&&... __args)
|
||||
: variant(in_place_index<__index_of<_Tp>>,
|
||||
|
@ -1342,8 +1351,8 @@ namespace __variant
|
|||
|
||||
template<typename _Tp, typename _Up, typename... _Args,
|
||||
typename = enable_if_t<__exactly_once<_Tp>
|
||||
&& is_constructible_v<
|
||||
_Tp, initializer_list<_Up>&, _Args&&...>>>
|
||||
&& is_constructible_v<_Tp,
|
||||
initializer_list<_Up>&, _Args...>>>
|
||||
constexpr explicit
|
||||
variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
|
||||
_Args&&... __args)
|
||||
|
@ -1352,8 +1361,8 @@ namespace __variant
|
|||
{ }
|
||||
|
||||
template<size_t _Np, typename... _Args,
|
||||
typename = enable_if_t<
|
||||
is_constructible_v<__to_type<_Np>, _Args&&...>>>
|
||||
typename _Tp = __to_type<_Np>,
|
||||
typename = enable_if_t<is_constructible_v<_Tp, _Args...>>>
|
||||
constexpr explicit
|
||||
variant(in_place_index_t<_Np>, _Args&&... __args)
|
||||
: _Base(in_place_index<_Np>, std::forward<_Args>(__args)...),
|
||||
|
@ -1361,8 +1370,10 @@ namespace __variant
|
|||
{ }
|
||||
|
||||
template<size_t _Np, typename _Up, typename... _Args,
|
||||
typename = enable_if_t<is_constructible_v<__to_type<_Np>,
|
||||
initializer_list<_Up>&, _Args&&...>>>
|
||||
typename _Tp = __to_type<_Np>,
|
||||
typename = enable_if_t<is_constructible_v<_Tp,
|
||||
initializer_list<_Up>&,
|
||||
_Args...>>>
|
||||
constexpr explicit
|
||||
variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
|
||||
_Args&&... __args)
|
||||
|
@ -1372,12 +1383,12 @@ namespace __variant
|
|||
|
||||
template<typename _Tp>
|
||||
enable_if_t<__exactly_once<__accepted_type<_Tp&&>>
|
||||
&& is_constructible_v<__accepted_type<_Tp&&>, _Tp&&>
|
||||
&& is_assignable_v<__accepted_type<_Tp&&>&, _Tp&&>
|
||||
&& !is_same_v<decay_t<_Tp>, variant>, variant&>
|
||||
&& is_constructible_v<__accepted_type<_Tp&&>, _Tp>
|
||||
&& is_assignable_v<__accepted_type<_Tp&&>&, _Tp>,
|
||||
variant&>
|
||||
operator=(_Tp&& __rhs)
|
||||
noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp&&>
|
||||
&& is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp&&>)
|
||||
noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp>
|
||||
&& is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp>)
|
||||
{
|
||||
constexpr auto __index = __accepted_index<_Tp&&>;
|
||||
if (index() == __index)
|
||||
|
|
|
@ -144,10 +144,15 @@ void arbitrary_ctor()
|
|||
static_assert(noexcept(variant<int, DefaultNoexcept>(DefaultNoexcept{})));
|
||||
}
|
||||
|
||||
struct none { none() = delete; };
|
||||
struct any { template <typename T> any(T&&) {} };
|
||||
|
||||
void in_place_index_ctor()
|
||||
{
|
||||
variant<string, string> a(in_place_index<0>, "a");
|
||||
variant<string, string> b(in_place_index<1>, {'a'});
|
||||
|
||||
static_assert(!is_constructible_v<variant<none, any>, std::in_place_index_t<0>>, "PR libstdc++/90165");
|
||||
}
|
||||
|
||||
void in_place_type_ctor()
|
||||
|
@ -155,6 +160,7 @@ void in_place_type_ctor()
|
|||
variant<int, string, int> a(in_place_type<string>, "a");
|
||||
variant<int, string, int> b(in_place_type<string>, {'a'});
|
||||
static_assert(!is_constructible_v<variant<string, string>, in_place_type_t<string>, const char*>);
|
||||
static_assert(!is_constructible_v<variant<none, any>, std::in_place_type_t<none>>, "PR libstdc++/90165");
|
||||
}
|
||||
|
||||
void dtor()
|
||||
|
|
Loading…
Reference in New Issue