On 29/12/19 12:07 +0100, Stephan Bergmann wrote:
On 05/12/2019 13:46, Jonathan Wakely wrote:
commit 5012548fd62526fdf5e04aeacee2b127efbac0e0
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Thu Dec 5 12:23:53 2019 +0000

   libstdc++: Define std::lexicographical_compare_three_way for C++20
           * include/bits/stl_algobase.h (lexicographical_compare_three_way):
           Define for C++20.
           * testsuite/25_algorithms/lexicographical_compare_three_way/1.cc: New
           test.
           * testsuite/25_algorithms/lexicographical_compare_three_way/
           constexpr.cc: New test.

diff --git a/libstdc++-v3/include/bits/stl_algobase.h 
b/libstdc++-v3/include/bits/stl_algobase.h
index 98d324827ed..a2fd306e6d0 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
[...]
@@ -1456,6 +1459,104 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
         __gnu_cxx::__ops::__iter_comp_iter(__comp));
    }
+#if __cpp_lib_three_way_comparison
+#if __cpp_lib_concepts
+  // Iter points to a contiguous range of unsigned narrow character type
+  // or std::byte, suitable for comparison by memcmp.
+  template<typename _Iter>
+    concept __is_byte_iter = contiguous_iterator<_Iter>
+      && __is_byte<iter_value_t<_Iter>>::__value != 0
+      && !__gnu_cxx::__numeric_traits<iter_value_t<_Iter>>::__is_signed;
+
+  // Return a struct with two members, initialized to the smaller of x and y
+  // (or x if they compare equal) and the result of the comparison x <=> y.
+  template<typename _Tp>
+    constexpr auto
+    __min_cmp(_Tp __x, _Tp __y)
+    {
+      struct _Res {
+       _Tp _M_min;
+       decltype(__x <=> __y) _M_cmp;
+      };
+      auto __c = __x <=> __y;
+      if (__c > 0)
+       return _Res{__y, __c};
+      return _Res{__x, __c};
+    }
+#endif
[...]
+
+  template<typename _InputIter1, typename _InputIter2>
+    constexpr auto
+    lexicographical_compare_three_way(_InputIter1 __first1,
+                                     _InputIter1 __last1,
+                                     _InputIter2 __first2,
+                                     _InputIter2 __last2)
+    {
+      return std::lexicographical_compare_three_way(__first1, __last1,
+                                                   __first2, __last2,
+                                                   compare_three_way{});

FYI, the above fails with -std=c++2a and recent Clang trunk after <https://github.com/llvm/llvm-project/commit/bc633a42dd409dbeb456263e3388b8caa4680aa0> "Mark the major papers for C++20 consistent comparisons as 'done', and start publishing the corresponding feature-test macro": Clang now defines __cpp_impl_three_way_comparison (so libstdc++-v3/include/std/version defines __cpp_lib_three_way_comparison) but still doesn't define __cpp_lib_concepts, so libstdc++-v3/libsupc++/compare doesn't define compare_three_way.

I locally managed that for now with extending the surrounding

#if __cpp_lib_three_way_comparison

with

&& __cpp_lib_concepts

+    }
+#endif // three_way_comparison

Should be fixed at r279861 on trunk (also attached). This leaves the
five-argument overload defined for Clang, just not the four-argument
one that uses std::compare_three_way.

We could define that overload unconditionally and do something like
this, but I prefer to just omit it rather than define it badly:

      return std::lexicographical_compare_three_way(__first1, __last1,
                                                    __first2, __last2,
#if __cpp_lib_concepts
                                                    compare_three_way{}
#else
                                                    [](auto&& __l, auto&& __r)
                                                    { return __l <=> __r; }
#endif // concepts
                                                    );


commit 9b51d80f860841ea80be6c420970ec8b881c0f9e
Author: redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Fri Jan 3 14:44:39 2020 +0000

    libstdc++: Only use std::compare_three_way when concepts are supported
    
    Clang now supports three-way comparisons. That causes both overloads of
    std::lexicographical_compare_three_way to be defined, but the second one
    uses std::compare_three_way which depends on concepts. Clang does not
    yet support concepts, so the second overload should also depend on
    __cpp_lib_concepts.
    
            * include/bits/stl_algobase.h (lexicographical_compare_three_way):
            Only define four-argument overload when __cpp_lib_concepts is defined.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@279861 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index 13de6aecc6c..76c323ab21b 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -1751,6 +1751,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	: __first2 != __last2 ? strong_ordering::less : strong_ordering::equal;
     }
 
+#if __cpp_lib_concepts
   template<typename _InputIter1, typename _InputIter2>
     constexpr auto
     lexicographical_compare_three_way(_InputIter1 __first1,
@@ -1762,6 +1763,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 						    __first2, __last2,
 						    compare_three_way{});
     }
+#endif // concepts
 #endif // three_way_comparison
 
   template<typename _InputIterator1, typename _InputIterator2,

Reply via email to