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.

Tested powerpc64le-linux, committed to trunk.

I'll consider a simpler version of this for gcc-8-branch, that just
applies the __not_in_place_tag constraint to the variant(T&&) ctor.

commit db75c3d6a787c315ed79ace15ef60206719b6420
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Tue Apr 23 12:24:05 2019 +0100

    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.

diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index b71bb027f2b..d65084eeb1f 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -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)
diff --git a/libstdc++-v3/testsuite/20_util/variant/compile.cc 
b/libstdc++-v3/testsuite/20_util/variant/compile.cc
index afd593d2fef..6acf5bc627e 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()

Reply via email to