aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-11-08 00:37:08 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2019-11-08 00:37:08 +0000
commit29669521665c5e82a8548ef0a7f642634a042d48 (patch)
tree1de0f458eeb597d38469f4cd353b8e1a119f55a3 /libstdc++-v3
parent780bc8922ba77cec3de90ce86eefedf54ad80c8f (diff)
downloadgcc-29669521665c5e82a8548ef0a7f642634a042d48.zip
gcc-29669521665c5e82a8548ef0a7f642634a042d48.tar.gz
gcc-29669521665c5e82a8548ef0a7f642634a042d48.tar.bz2
libstdc++: define std::common_comparison_category for C++20
* libsupc++/compare (common_comparison_category) (common_comparison_category_t): Define for C++20. * testsuite/18_support/comparisons/common/1.cc: New test. From-SVN: r277943
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog4
-rw-r--r--libstdc++-v3/libsupc++/compare99
-rw-r--r--libstdc++-v3/testsuite/18_support/comparisons/common/1.cc48
3 files changed, 133 insertions, 18 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 3139914..65e55d0 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,9 @@
2019-11-07 Jonathan Wakely <jwakely@redhat.com>
+ * libsupc++/compare (common_comparison_category)
+ (common_comparison_category_t): Define for C++20.
+ * testsuite/18_support/comparisons/common/1.cc: New test.
+
* include/bits/stl_algo.h (for_each_n): Handle negative count.
* testsuite/25_algorithms/for_each/for_each_n_debug.cc: New test.
diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare
index 84cc3f5..94728e2 100644
--- a/libstdc++-v3/libsupc++/compare
+++ b/libstdc++-v3/libsupc++/compare
@@ -385,18 +385,81 @@ namespace std
is_gteq(partial_ordering __cmp) noexcept
{ return __cmp >= 0; }
+#if __cpp_lib_concepts
+ namespace __detail
+ {
+ template<typename _Tp>
+ inline constexpr unsigned __cmp_cat_id = 1;
+ template<>
+ inline constexpr unsigned __cmp_cat_id<strong_ordering> = 2;
+ template<>
+ inline constexpr unsigned __cmp_cat_id<weak_ordering> = 4;
+ template<>
+ inline constexpr unsigned __cmp_cat_id<partial_ordering> = 8;
+
+ template<typename... _Ts>
+ constexpr unsigned __cmp_cat_ids()
+ { return (__cmp_cat_id<_Ts> | ...); }
+
+ template<unsigned>
+ struct __common_cmp_cat;
+
+ // If any Ti is not a comparison category type, U is void.
+ template<unsigned _Bits>
+ requires ((_Bits & 1) == 1)
+ struct __common_cmp_cat<_Bits> { using type = void; };
+
+ // Otherwise, if at least one Ti is std::partial_ordering,
+ // U is std::partial_ordering.
+ template<unsigned _Bits>
+ requires ((_Bits & 0b1001) == 0b1000)
+ struct __common_cmp_cat<_Bits> { using type = partial_ordering; };
+
+ // Otherwise, if at least one Ti is std::weak_ordering,
+ // U is std::weak_ordering.
+ template<unsigned _Bits>
+ requires ((_Bits & 0b1101) == 0b0100)
+ struct __common_cmp_cat<_Bits> { using type = weak_ordering; };
+
+ // Otherwise, U is std::strong_ordering.
+ template<>
+ struct __common_cmp_cat<0b0010> { using type = strong_ordering; };
+ } // namespace __detail
+
// [cmp.common], common comparison category type
template<typename... _Ts>
struct common_comparison_category
{
- // using type = TODO
+ using type
+ = __detail::__common_cmp_cat<__detail::__cmp_cat_ids<_Ts...>()>::type;
};
+ // Partial specializations for one and zero argument cases.
+
+ template<typename _Tp>
+ struct common_comparison_category<_Tp>
+ { using type = void; };
+
+ template<>
+ struct common_comparison_category<partial_ordering>
+ { using type = partial_ordering; };
+
+ template<>
+ struct common_comparison_category<weak_ordering>
+ { using type = weak_ordering; };
+
+ template<>
+ struct common_comparison_category<strong_ordering>
+ { using type = strong_ordering; };
+
+ template<>
+ struct common_comparison_category<>
+ { using type = strong_ordering; };
+
template<typename... _Ts>
using common_comparison_category_t
= typename common_comparison_category<_Ts...>::type;
-#if __cpp_lib_concepts
namespace __detail
{
template<typename _Tp, typename _Cat>
@@ -493,22 +556,22 @@ namespace std
template<typename _Tp, typename _Up>
requires (three_way_comparable_with<_Tp, _Up>
|| __detail::__3way_builtin_ptr_cmp<_Tp, _Up>)
- constexpr auto
- operator()(_Tp&& __t, _Up&& __u) const noexcept
- {
- if constexpr (__detail::__3way_builtin_ptr_cmp<_Tp, _Up>)
- {
- auto __pt = static_cast<const volatile void*>(__t);
- auto __pu = static_cast<const volatile void*>(__u);
- if (__builtin_is_constant_evaluated())
- return __pt <=> __pu;
- auto __it = reinterpret_cast<__UINTPTR_TYPE__>(__pt);
- auto __iu = reinterpret_cast<__UINTPTR_TYPE__>(__pu);
- return __it <=> __iu;
- }
- else
- return static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u);
- }
+ constexpr auto
+ operator()(_Tp&& __t, _Up&& __u) const noexcept
+ {
+ if constexpr (__detail::__3way_builtin_ptr_cmp<_Tp, _Up>)
+ {
+ auto __pt = static_cast<const volatile void*>(__t);
+ auto __pu = static_cast<const volatile void*>(__u);
+ if (__builtin_is_constant_evaluated())
+ return __pt <=> __pu;
+ auto __it = reinterpret_cast<__UINTPTR_TYPE__>(__pt);
+ auto __iu = reinterpret_cast<__UINTPTR_TYPE__>(__pu);
+ return __it <=> __iu;
+ }
+ else
+ return static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u);
+ }
using is_transparent = void;
};
diff --git a/libstdc++-v3/testsuite/18_support/comparisons/common/1.cc b/libstdc++-v3/testsuite/18_support/comparisons/common/1.cc
new file mode 100644
index 0000000..015a8ac
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/comparisons/common/1.cc
@@ -0,0 +1,48 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <compare>
+
+template<typename Cat, typename... T>
+constexpr bool check()
+{
+ return std::same_as<Cat, std::common_comparison_category_t<T...>>;
+}
+
+using std::partial_ordering;
+using std::weak_ordering;
+using std::strong_ordering;
+
+static_assert(check<strong_ordering>());
+static_assert(check<void, int>());
+static_assert(check<void, int, int>());
+static_assert(check<void, weak_ordering, int>());
+static_assert(check<void, int, partial_ordering>());
+static_assert(check<partial_ordering, partial_ordering>());
+static_assert(check<partial_ordering, weak_ordering, partial_ordering>());
+
+using PO = std::partial_ordering;
+using WO = std::weak_ordering;
+using SO = std::strong_ordering;
+
+static_assert(check<PO, SO, PO, SO, SO>());
+static_assert(check<PO, SO, PO, SO, WO>());
+static_assert(check<WO, SO, WO, SO, WO>());
+static_assert(check<SO, SO, SO, SO, SO>());