[PATCH] Implement P0393R3

Tim Shen via gcc-patches gcc-patches@gcc.gnu.org
Mon Jan 9 06:49:00 GMT 2017


On Tue, Jan 3, 2017 at 6:17 AM, Jonathan Wakely <jwakely@redhat.com> wrote:
> On 01/01/17 04:17 -0800, Tim Shen via libstdc++ wrote:
>>
>> +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__op, __name) \
>> +  template<typename... _Types> \
>> +    constexpr bool operator __op(const variant<_Types...>& __lhs, \
>> +                                const variant<_Types...>& __rhs) \
>> +    { \
>> +      return __lhs._M##__name(__rhs,
>> std::index_sequence_for<_Types...>{}); \
>> +    } \
>> +\
>> +  constexpr bool operator __op(monostate, monostate) noexcept \
>> +  { return 0 __op 0; }
>> +
>> +  _VARIANT_RELATION_FUNCTION_TEMPLATE(<, _erased_less_than)
>> +  _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, _erased_less_equal)
>> +  _VARIANT_RELATION_FUNCTION_TEMPLATE(==, _erased_equal)
>> +  _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, _erased_not_equal)
>> +  _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, _erased_greater_than)
>> +  _VARIANT_RELATION_FUNCTION_TEMPLATE(>, _erased_greater)
>
>
> These need double underscore prefixes.

Done.

>
> Still reviewing the rest ...
>



-- 
Regards,
Tim Shen
-------------- next part --------------
commit fba8c3c8cca773a501766aff90b13f72e42d9355
Author: Tim Shen <timshen@google.com>
Date:   Sun Jan 1 04:07:15 2017 -0800

    2017-01-01  Tim Shen  <timshen@google.com>
    
            PR libstdc++/78723
            * include/std/variant: Implement P0393R3.
            * testsuite/20_util/variant/compile.cc: Adjust tests.
            * testsuite/20_util/variant/run.cc: Adjust tests.

diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index 3d025a7..9ca61d6 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -263,21 +263,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       swap(__ref_cast<_Lhs>(__lhs), __ref_cast<_Rhs>(__rhs));
     }
 
-  template<typename _Variant, size_t _Np>
-    constexpr bool
-    __erased_equal_to(_Variant&& __lhs, _Variant&& __rhs)
-    {
-      return __get<_Np>(std::forward<_Variant>(__lhs))
-	  == __get<_Np>(std::forward<_Variant>(__rhs));
+#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__op, __function_name) \
+  template<typename _Variant, size_t _Np> \
+    constexpr bool \
+    __function_name(const _Variant& __lhs, const _Variant& __rhs) \
+    { \
+      return __get<_Np>(std::forward<_Variant>(__lhs)) \
+	  __op __get<_Np>(std::forward<_Variant>(__rhs)); \
     }
 
-  template<typename _Variant, size_t _Np>
-    constexpr bool
-    __erased_less_than(const _Variant& __lhs, const _Variant& __rhs)
-    {
-      return __get<_Np>(std::forward<_Variant>(__lhs))
-	  < __get<_Np>(std::forward<_Variant>(__rhs));
-    }
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(<, __erased_less_than)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, __erased_less_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(==, __erased_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, __erased_not_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, __erased_greater_than)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(>, __erased_greater)
+
+#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
 
   template<typename _Tp>
     constexpr size_t
@@ -800,63 +802,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(__ptr);
     }
 
-  template<typename... _Types>
-    constexpr bool operator==(const variant<_Types...>& __lhs,
-			      const variant<_Types...>& __rhs)
-    {
-      return __lhs._M_equal_to(__rhs, std::index_sequence_for<_Types...>{});
-    }
-
-  template<typename... _Types>
-    constexpr inline bool
-    operator!=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs)
-    { return !(__lhs == __rhs); }
-
-  template<typename... _Types>
-    constexpr inline bool
-    operator<(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs)
-    {
-      return __lhs._M_less_than(__rhs, std::index_sequence_for<_Types...>{});
-    }
-
-  template<typename... _Types>
-    constexpr inline bool
-    operator>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs)
-    { return __rhs < __lhs; }
-
-  template<typename... _Types>
-    constexpr inline bool
-    operator<=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs)
-    { return !(__lhs > __rhs); }
+  struct monostate { };
 
-  template<typename... _Types>
-    constexpr inline bool
-    operator>=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs)
-    { return !(__lhs < __rhs); }
+#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__op, __name) \
+  template<typename... _Types> \
+    constexpr bool operator __op(const variant<_Types...>& __lhs, \
+				 const variant<_Types...>& __rhs) \
+    { \
+      return __lhs._M##__name(__rhs, std::index_sequence_for<_Types...>{}); \
+    } \
+\
+  constexpr bool operator __op(monostate, monostate) noexcept \
+  { return 0 __op 0; }
+
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(<, __erased_less_than)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, __erased_less_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(==, __erased_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, __erased_not_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, __erased_greater_than)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(>, __erased_greater)
+
+#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
 
   template<typename _Visitor, typename... _Variants>
     constexpr decltype(auto) visit(_Visitor&&, _Variants&&...);
 
-  struct monostate { };
-
-  constexpr bool operator<(monostate, monostate) noexcept
-  { return false; }
-
-  constexpr bool operator>(monostate, monostate) noexcept
-  { return false; }
-
-  constexpr bool operator<=(monostate, monostate) noexcept
-  { return true; }
-
-  constexpr bool operator>=(monostate, monostate) noexcept
-  { return true; }
-
-  constexpr bool operator==(monostate, monostate) noexcept
-  { return true; }
-
-  constexpr bool operator!=(monostate, monostate) noexcept
-  { return false; }
-
   template<typename... _Types>
     inline enable_if_t<(is_move_constructible_v<_Types> && ...)
 			&& (is_swappable_v<_Types> && ...)>
@@ -1122,51 +1092,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
 
     private:
-      template<size_t... __indices>
-	static constexpr bool
-	(*_S_equal_to_vtable[])(const variant&, const variant&) =
-	  { &__detail::__variant::__erased_equal_to<
-	    const variant&, __indices>... };
-
-      template<size_t... __indices>
-	static constexpr bool
-	(*_S_less_than_vtable[])(const variant&, const variant&) =
-	  { &__detail::__variant::__erased_less_than<
-	      const variant&, __indices>... };
-
-      template<size_t... __indices>
-	constexpr bool
-	_M_equal_to(const variant& __rhs,
-		    std::index_sequence<__indices...>) const
-	{
-	  if (this->index() != __rhs.index())
-	    return false;
-
-	  if (this->valueless_by_exception())
-	    return true;
-
-	  return _S_equal_to_vtable<__indices...>[this->index()](*this, __rhs);
+#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__op, __name) \
+      template<size_t... __indices> \
+	static constexpr bool \
+	(*_S##__name##_vtable[])(const variant&, const variant&) = \
+	  { &__detail::__variant::__name<const variant&, __indices>... }; \
+      template<size_t... __indices> \
+	constexpr inline bool \
+	_M##__name(const variant& __rhs, \
+		     std::index_sequence<__indices...>) const \
+	{ \
+	  auto __lhs_index = this->index(); \
+	  auto __rhs_index = __rhs.index(); \
+	  if (__lhs_index != __rhs_index || valueless_by_exception()) \
+	    /* Intentinoal modulo addition. */ \
+	    return __lhs_index + 1 __op __rhs_index + 1; \
+	  return _S##__name##_vtable<__indices...>[__lhs_index](*this, __rhs); \
 	}
 
-      template<size_t... __indices>
-	constexpr inline bool
-	_M_less_than(const variant& __rhs,
-		     std::index_sequence<__indices...>) const
-	{
-	  auto __lhs_index = this->index();
-	  auto __rhs_index = __rhs.index();
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(<, __erased_less_than)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, __erased_less_equal)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(==, __erased_equal)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, __erased_not_equal)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, __erased_greater_than)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(>, __erased_greater)
 
-	  if (__lhs_index < __rhs_index)
-	    return true;
-
-	  if (__lhs_index > __rhs_index)
-	    return false;
-
-	  if (this->valueless_by_exception())
-	    return false;
-
-	  return _S_less_than_vtable<__indices...>[__lhs_index](*this, __rhs);
-	}
+#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
 
       template<size_t _Np, typename _Vp>
 	friend constexpr decltype(auto) __detail::__variant::
@@ -1182,15 +1133,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
         __get_storage(_Vp&& __v);
 
-      template<typename... _Tp>
-	friend constexpr bool
-	operator==(const variant<_Tp...>& __lhs,
-		   const variant<_Tp...>& __rhs);
+#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__op) \
+      template<typename... _Tp> \
+	friend constexpr bool \
+	operator __op(const variant<_Tp...>& __lhs, \
+		      const variant<_Tp...>& __rhs);
+
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(<)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(<=)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(==)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(!=)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(>=)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(>)
 
-      template<typename... _Tp>
-	friend constexpr bool
-	operator<(const variant<_Tp...>& __lhs,
-		  const variant<_Tp...>& __rhs);
+#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
     };
 
   template<size_t _Np, typename... _Types>
diff --git a/libstdc++-v3/testsuite/20_util/variant/compile.cc b/libstdc++-v3/testsuite/20_util/variant/compile.cc
index 65f4326..8320013 100644
--- a/libstdc++-v3/testsuite/20_util/variant/compile.cc
+++ b/libstdc++-v3/testsuite/20_util/variant/compile.cc
@@ -65,7 +65,11 @@ struct nonliteral
   nonliteral() { }
 
   bool operator<(const nonliteral&) const;
+  bool operator<=(const nonliteral&) const;
   bool operator==(const nonliteral&) const;
+  bool operator!=(const nonliteral&) const;
+  bool operator>=(const nonliteral&) const;
+  bool operator>(const nonliteral&) const;
 };
 
 void default_ctor()
diff --git a/libstdc++-v3/testsuite/20_util/variant/run.cc b/libstdc++-v3/testsuite/20_util/variant/run.cc
index 121fd22..db4529e 100644
--- a/libstdc++-v3/testsuite/20_util/variant/run.cc
+++ b/libstdc++-v3/testsuite/20_util/variant/run.cc
@@ -47,6 +47,13 @@ struct AlwaysThrow
     throw nullptr;
     return *this;
   }
+
+  bool operator<(const AlwaysThrow&) const { VERIFY(false); }
+  bool operator<=(const AlwaysThrow&) const { VERIFY(false); }
+  bool operator==(const AlwaysThrow&) const { VERIFY(false); }
+  bool operator!=(const AlwaysThrow&) const { VERIFY(false); }
+  bool operator>=(const AlwaysThrow&) const { VERIFY(false); }
+  bool operator>(const AlwaysThrow&) const { VERIFY(false); }
 };
 
 void default_ctor()
@@ -229,6 +236,23 @@ void test_relational()
 
   VERIFY((variant<int, string>(2) < variant<int, string>("a")));
   VERIFY((variant<string, int>(2) > variant<string, int>("a")));
+
+  {
+    variant<int, AlwaysThrow> v, w;
+    try
+      {
+	AlwaysThrow a;
+	v = a;
+      }
+    catch (nullptr_t) { }
+    VERIFY(v.valueless_by_exception());
+    VERIFY(v < w);
+    VERIFY(v <= w);
+    VERIFY(!(v == w));
+    VERIFY(v != w);
+    VERIFY(w > v);
+    VERIFY(w >= v);
+  }
 }
 
 void test_swap()


More information about the Gcc-patches mailing list