diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2019-04-23 13:48:18 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2019-04-23 13:48:18 +0100 |
commit | 06715e1cfb475a89b2890951008e70325bdd0ce4 (patch) | |
tree | c0de0775fe9a41f20b60738dd6b7b1f4415ea0e6 | |
parent | 82e8c3da7408bc0695511ee13f88d451c8adadd8 (diff) | |
download | gcc-06715e1cfb475a89b2890951008e70325bdd0ce4.zip gcc-06715e1cfb475a89b2890951008e70325bdd0ce4.tar.gz gcc-06715e1cfb475a89b2890951008e70325bdd0ce4.tar.bz2 |
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
-rw-r--r-- | libstdc++-v3/ChangeLog | 20 | ||||
-rw-r--r-- | libstdc++-v3/include/std/variant | 65 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/variant/compile.cc | 6 |
3 files changed, 64 insertions, 27 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f04a7e0..1d0192b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -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. diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index b71bb02..d65084e 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -1285,6 +1285,10 @@ namespace __variant 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> - struct __to_type_impl<_Np, true> - { using type = variant_alternative_t<_Np, variant>; }; + template<size_t _Np, typename = enable_if_t<(_Np < sizeof...(_Types))>> + using __to_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) diff --git a/libstdc++-v3/testsuite/20_util/variant/compile.cc b/libstdc++-v3/testsuite/20_util/variant/compile.cc index afd593d..6acf5bc 100644 --- a/libstdc++-v3/testsuite/20_util/variant/compile.cc +++ b/libstdc++-v3/testsuite/20_util/variant/compile.cc @@ -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() |