On 03/01/20 15:03 +0000, Jonathan Wakely wrote:
On 03/01/20 14:54 +0000, Jonathan Wakely wrote:
On 29/12/19 12:07 +0100, Stephan Bergmann wrote:
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
                                                    );

After writing that, I realised that a better approach might be:

--- a/libstdc++-v3/libsupc++/compare
+++ b/libstdc++-v3/libsupc++/compare
@@ -40,7 +40,9 @@

namespace std
{
-#define __cpp_lib_three_way_comparison 201711L
+#if __cpp_lib_concepts
+# define __cpp_lib_three_way_comparison 201711L
+#endif

  // [cmp.categories], comparison category types


i.e. don't pretend the library supports three-way comparison if that
support is incomplete. That will still fix the Clang problem because
if that macro isn't defined then we don't define either overload of
std::lexicographical_compare_three_way.

That seems cleaner to me. Anybody disagree?


I'm committing this patch to do that.

Tested powerpc64le-linux, committed to trunk.


commit 6eb2a600ef9623cf6fbf2584df44fc5d71fd16f5
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Mon Jan 6 10:35:48 2020 +0000

    libstdc++: Define __cpp_lib_three_way_comparison conditionally
    
    The contents of the <compare> header are not complete unless concepts
    are supported, so the feature test macro should depend on the macro for
    concepts.
    
    As a result, the std::lexicographical_compare_three_way function will
    not be defined unless concepts are supported, so there is no need to
    check __cpp_lib_concepts before using concepts in those functions.
    
            * include/bits/stl_algobase.h (__is_byte_iter, __min_cmp)
            (lexicographical_compare_three_way): Do not depend on
            __cpp_lib_concepts.
            * include/std/version (__cpp_lib_three_way_comparison): Only define
            when __cpp_lib_concepts is defined.
            * libsupc++/compare (__cpp_lib_three_way_comparison): Likewise.

diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index 76c323ab21b..dc922a0f3d2 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -1667,7 +1667,6 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     }
 
 #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>
@@ -1690,7 +1689,6 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	return _Res{__y, __c};
       return _Res{__x, __c};
     }
-#endif
 
   /**
    *  @brief Performs dictionary comparison on ranges.
@@ -1718,7 +1716,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first1, __last1);
       __glibcxx_requires_valid_range(__first2, __last2);
 
-#if __cpp_lib_concepts && __cpp_lib_is_constant_evaluated
+#if __cpp_lib_is_constant_evaluated
       using _Cat = decltype(__comp(*__first1, *__first2));
       static_assert(same_as<common_comparison_category_t<_Cat>, _Cat>);
 
@@ -1739,7 +1737,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 		  }
 		return __lencmp;
 	      }
-#endif // concepts && is_constant_evaluated
+#endif // is_constant_evaluated
       while (__first1 != __last1 && __first2 != __last2)
 	{
 	  if (auto __cmp = __comp(*__first1, *__first2); __cmp != 0)
@@ -1751,7 +1749,6 @@ _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,
@@ -1763,7 +1760,6 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 						    __first2, __last2,
 						    compare_three_way{});
     }
-#endif // concepts
 #endif // three_way_comparison
 
   template<typename _InputIterator1, typename _InputIterator2,
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index ab8111468e4..81b9112e02a 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -191,7 +191,7 @@
 #define __cpp_lib_list_remove_return_type 201806L
 #define __cpp_lib_math_constants 201907L
 #define __cpp_lib_span 201902L
-#if __cpp_impl_three_way_comparison >= 201907L
+#if __cpp_impl_three_way_comparison >= 201907L && __cpp_lib_concepts
 # define __cpp_lib_three_way_comparison 201711L
 #endif
 #define __cpp_lib_to_array 201907L
diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare
index 31969fb5c04..98a592cbb14 100644
--- a/libstdc++-v3/libsupc++/compare
+++ b/libstdc++-v3/libsupc++/compare
@@ -38,10 +38,12 @@
 
 #include <concepts>
 
+#if __cpp_lib_concepts
+# define __cpp_lib_three_way_comparison 201711L
+#endif
+
 namespace std
 {
-#define __cpp_lib_three_way_comparison 201711L
-
   // [cmp.categories], comparison category types
 
   namespace __cmp_cat

Reply via email to