re PR libstdc++/78723 ([variant] P0393r3: "Making variant greater equal again" is...
authorTim Shen <timshen@google.com>
Wed, 15 Feb 2017 09:01:06 +0000 (09:01 +0000)
committerTim Shen <timshen@gcc.gnu.org>
Wed, 15 Feb 2017 09:01:06 +0000 (09:01 +0000)
PR libstdc++/78723
* include/std/variant (operator<(), operator>(), operator<=(),
operator>=(), operator==(), operator!=()): Implement P0393R3.
* testsuite/20_util/variant/compile.cc: Adjust tests.
* testsuite/20_util/variant/run.cc: Adjust tests.

From-SVN: r245475

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/variant
libstdc++-v3/testsuite/20_util/variant/compile.cc
libstdc++-v3/testsuite/20_util/variant/run.cc

index ec6e601c1ef42eff3c25ab38e018349829f84e0d..5ce466fa9ec72b17e73d5afdacea1bccfe6a8050 100644 (file)
@@ -1,3 +1,11 @@
+2017-02-15  Tim Shen  <timshen@google.com>
+
+       PR libstdc++/78723
+       * include/std/variant (operator<(), operator>(), operator<=(),
+       operator>=(), operator==(), operator!=()): Implement P0393R3.
+       * testsuite/20_util/variant/compile.cc: Adjust tests.
+       * testsuite/20_util/variant/run.cc: Adjust tests.
+
 2017-02-15  Tim Shen  <timshen@google.com>
 
        PR libstdc++/79513
index 866c4c40a618b16e2d48ae1a05dca745d0f1eef0..0cc50d03c4d0b5815e8c0de51438471e20b2a1a2 100644 (file)
@@ -264,21 +264,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, __NAME) \
+  template<typename _Variant, size_t _Np> \
+    constexpr bool \
+    __erased_##__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(<, less)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
+
+#undef _VARIANT_RELATION_FUNCTION_TEMPLATE
 
   template<typename _Tp>
     constexpr size_t
@@ -813,63 +815,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(<, less)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(>, 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> && ...)>
@@ -1140,51 +1110,33 @@ _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_erased_##__NAME[])(const variant&, const variant&) = \
+         { &__detail::__variant::__erased_##__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()) \
+           /* Modulo addition. */ \
+           return __lhs_index + 1 __OP __rhs_index + 1; \
+         return _S_erased_##__NAME<__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(<, less)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
+      _VARIANT_RELATION_FUNCTION_TEMPLATE(>, 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::
@@ -1200,15 +1152,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>
index 3bf9d5bfba3b18a794b7bffa2922f8b3574a306b..06e8eb31ee88dbf9b0305b0d16667422480e4170 100644 (file)
@@ -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()
index 121fd22527daf1efa1137a7d8ebb09bdac0fe97e..db4529eea3f53b864fe34294678083ed89c4d836 100644 (file)
@@ -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()