[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