[libcxx-commits] [libcxx] e07ca2a - [libcxx] Fix std::equal not accepting volatile types by refactoring __equal_to

Alvin Wong via libcxx-commits libcxx-commits at lists.llvm.org
Tue Nov 22 00:35:56 PST 2022


Author: Alvin Wong
Date: 2022-11-22T16:33:38+08:00
New Revision: e07ca2aeeb2f641e62f6ac7359472eb50111ea00

URL: https://github.com/llvm/llvm-project/commit/e07ca2aeeb2f641e62f6ac7359472eb50111ea00
DIFF: https://github.com/llvm/llvm-project/commit/e07ca2aeeb2f641e62f6ac7359472eb50111ea00.diff

LOG: [libcxx] Fix std::equal not accepting volatile types by refactoring __equal_to

Fixes https://github.com/llvm/llvm-project/issues/59021

Reviewed By: #libc, philnik

Differential Revision: https://reviews.llvm.org/D138268

Added: 
    

Modified: 
    libcxx/include/__algorithm/adjacent_find.h
    libcxx/include/__algorithm/comp.h
    libcxx/include/__algorithm/equal.h
    libcxx/include/__algorithm/find_end.h
    libcxx/include/__algorithm/find_first_of.h
    libcxx/include/__algorithm/is_permutation.h
    libcxx/include/__algorithm/mismatch.h
    libcxx/include/__algorithm/search.h
    libcxx/include/__algorithm/search_n.h
    libcxx/include/__algorithm/unique.h
    libcxx/include/__algorithm/unique_copy.h
    libcxx/include/forward_list
    libcxx/include/list
    libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__algorithm/adjacent_find.h b/libcxx/include/__algorithm/adjacent_find.h
index 9916d9007bb14..30df4a976f3d8 100644
--- a/libcxx/include/__algorithm/adjacent_find.h
+++ b/libcxx/include/__algorithm/adjacent_find.h
@@ -45,8 +45,7 @@ adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicat
 template <class _ForwardIterator>
 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
 adjacent_find(_ForwardIterator __first, _ForwardIterator __last) {
-  typedef typename iterator_traits<_ForwardIterator>::value_type __v;
-  return std::adjacent_find(std::move(__first), std::move(__last), __equal_to<__v>());
+  return std::adjacent_find(std::move(__first), std::move(__last), __equal_to());
 }
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/__algorithm/comp.h b/libcxx/include/__algorithm/comp.h
index 7fa5c39cd4eb0..af8eb7b5d76b1 100644
--- a/libcxx/include/__algorithm/comp.h
+++ b/libcxx/include/__algorithm/comp.h
@@ -17,37 +17,11 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-// I'd like to replace these with _VSTD::equal_to<void>, but can't because:
-//   * That only works with C++14 and later, and
-//   * We haven't included <functional> here.
-template <class _T1, class _T2 = _T1>
-struct __equal_to
-{
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(const _T1& __x, const _T2& __y) const {return __x == __y;}
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(const _T2& __x, const _T1& __y) const {return __x == __y;}
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(const _T2& __x, const _T2& __y) const {return __x == __y;}
-};
-
-template <class _T1>
-struct __equal_to<_T1, _T1>
-{
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
-    bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
-};
-
-template <class _T1>
-struct __equal_to<const _T1, _T1>
-{
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
-    bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
-};
-
-template <class _T1>
-struct __equal_to<_T1, const _T1>
-{
-    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
-    bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
+struct __equal_to {
+  template <class _T1, class _T2>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(const _T1& __x, const _T2& __y) const {
+    return __x == __y;
+  }
 };
 
 template <class _T1, class _T2 = _T1>

diff  --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h
index b46adea4ab3f1..cf37f46aaf69e 100644
--- a/libcxx/include/__algorithm/equal.h
+++ b/libcxx/include/__algorithm/equal.h
@@ -33,9 +33,7 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first
 template <class _InputIterator1, class _InputIterator2>
 _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
 equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) {
-  typedef typename iterator_traits<_InputIterator1>::value_type __v1;
-  typedef typename iterator_traits<_InputIterator2>::value_type __v2;
-  return _VSTD::equal(__first1, __last1, __first2, __equal_to<__v1, __v2>());
+  return std::equal(__first1, __last1, __first2, __equal_to());
 }
 
 #if _LIBCPP_STD_VER > 11
@@ -72,11 +70,14 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first
 template <class _InputIterator1, class _InputIterator2>
 _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
 equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) {
-  typedef typename iterator_traits<_InputIterator1>::value_type __v1;
-  typedef typename iterator_traits<_InputIterator2>::value_type __v2;
-  return _VSTD::__equal(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>(),
-                        typename iterator_traits<_InputIterator1>::iterator_category(),
-                        typename iterator_traits<_InputIterator2>::iterator_category());
+  return std::__equal(
+      __first1,
+      __last1,
+      __first2,
+      __last2,
+      __equal_to(),
+      typename iterator_traits<_InputIterator1>::iterator_category(),
+      typename iterator_traits<_InputIterator2>::iterator_category());
 }
 #endif
 

diff  --git a/libcxx/include/__algorithm/find_end.h b/libcxx/include/__algorithm/find_end.h
index 72b07bb2b472f..e2fee6b3c4596 100644
--- a/libcxx/include/__algorithm/find_end.h
+++ b/libcxx/include/__algorithm/find_end.h
@@ -219,9 +219,7 @@ template <class _ForwardIterator1, class _ForwardIterator2>
 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
 _ForwardIterator1 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
                            _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
-  using __v1 = typename iterator_traits<_ForwardIterator1>::value_type;
-  using __v2 = typename iterator_traits<_ForwardIterator2>::value_type;
-  return std::find_end(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>());
+  return std::find_end(__first1, __last1, __first2, __last2, __equal_to());
 }
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/__algorithm/find_first_of.h b/libcxx/include/__algorithm/find_first_of.h
index 9d38b9c394a32..12f0109a616c3 100644
--- a/libcxx/include/__algorithm/find_first_of.h
+++ b/libcxx/include/__algorithm/find_first_of.h
@@ -44,9 +44,7 @@ find_first_of(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIte
 template <class _ForwardIterator1, class _ForwardIterator2>
 _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of(
     _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
-  typedef typename iterator_traits<_ForwardIterator1>::value_type __v1;
-  typedef typename iterator_traits<_ForwardIterator2>::value_type __v2;
-  return _VSTD::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>());
+  return std::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to());
 }
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/__algorithm/is_permutation.h b/libcxx/include/__algorithm/is_permutation.h
index 2e17ae649b70d..005445652e9df 100644
--- a/libcxx/include/__algorithm/is_permutation.h
+++ b/libcxx/include/__algorithm/is_permutation.h
@@ -199,24 +199,23 @@ is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIt
 template <class _ForwardIterator1, class _ForwardIterator2>
 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
 is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) {
-  using __v1 = __iter_value_type<_ForwardIterator1>;
-  using __v2 = __iter_value_type<_ForwardIterator2>;
-  return std::is_permutation(__first1, __last1, __first2, __equal_to<__v1, __v2>());
+  return std::is_permutation(__first1, __last1, __first2, __equal_to());
 }
 
 #if _LIBCPP_STD_VER > 11
 
 // 2+2 iterators
 template <class _ForwardIterator1, class _ForwardIterator2>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
-is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-               _ForwardIterator2 __last2) {
-  using __v1 = __iter_value_type<_ForwardIterator1>;
-  using __v2 = __iter_value_type<_ForwardIterator2>;
-
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation(
+    _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
   return std::__is_permutation<_ClassicAlgPolicy>(
-      std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2),
-      __equal_to<__v1, __v2>(), __identity(), __identity());
+      std::move(__first1),
+      std::move(__last1),
+      std::move(__first2),
+      std::move(__last2),
+      __equal_to(),
+      __identity(),
+      __identity());
 }
 
 // 2+2 iterators, predicate

diff  --git a/libcxx/include/__algorithm/mismatch.h b/libcxx/include/__algorithm/mismatch.h
index b386245a353f6..600e2cdd3da4f 100644
--- a/libcxx/include/__algorithm/mismatch.h
+++ b/libcxx/include/__algorithm/mismatch.h
@@ -35,9 +35,7 @@ template <class _InputIterator1, class _InputIterator2>
 _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY
     _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2>
     mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) {
-  typedef typename iterator_traits<_InputIterator1>::value_type __v1;
-  typedef typename iterator_traits<_InputIterator2>::value_type __v2;
-  return _VSTD::mismatch(__first1, __last1, __first2, __equal_to<__v1, __v2>());
+  return std::mismatch(__first1, __last1, __first2, __equal_to());
 }
 
 #if _LIBCPP_STD_VER > 11
@@ -56,9 +54,7 @@ template <class _InputIterator1, class _InputIterator2>
 _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY
     _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2>
     mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) {
-  typedef typename iterator_traits<_InputIterator1>::value_type __v1;
-  typedef typename iterator_traits<_InputIterator2>::value_type __v2;
-  return _VSTD::mismatch(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>());
+  return std::mismatch(__first1, __last1, __first2, __last2, __equal_to());
 }
 #endif
 

diff  --git a/libcxx/include/__algorithm/search.h b/libcxx/include/__algorithm/search.h
index f22a1bb016f1e..93771be39e35b 100644
--- a/libcxx/include/__algorithm/search.h
+++ b/libcxx/include/__algorithm/search.h
@@ -184,9 +184,7 @@ template <class _ForwardIterator1, class _ForwardIterator2>
 _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
 _ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
                          _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
-  using __v1 = typename iterator_traits<_ForwardIterator1>::value_type;
-  using __v2 = typename iterator_traits<_ForwardIterator2>::value_type;
-  return std::search(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>());
+  return std::search(__first1, __last1, __first2, __last2, __equal_to());
 }
 
 #if _LIBCPP_STD_VER > 14

diff  --git a/libcxx/include/__algorithm/search_n.h b/libcxx/include/__algorithm/search_n.h
index b3fd911442fba..60a073565156e 100644
--- a/libcxx/include/__algorithm/search_n.h
+++ b/libcxx/include/__algorithm/search_n.h
@@ -173,8 +173,7 @@ _ForwardIterator search_n(_ForwardIterator __first, _ForwardIterator __last,
 template <class _ForwardIterator, class _Size, class _Tp>
 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
 _ForwardIterator search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value) {
-  typedef typename iterator_traits<_ForwardIterator>::value_type __v;
-  return std::search_n(__first, __last, std::__convert_to_integral(__count), __value, __equal_to<__v, _Tp>());
+  return std::search_n(__first, __last, std::__convert_to_integral(__count), __value, __equal_to());
 }
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/__algorithm/unique.h b/libcxx/include/__algorithm/unique.h
index f2733a7e5d48b..1717a00c8a934 100644
--- a/libcxx/include/__algorithm/unique.h
+++ b/libcxx/include/__algorithm/unique.h
@@ -51,8 +51,7 @@ unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pre
 template <class _ForwardIterator>
 _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
 unique(_ForwardIterator __first, _ForwardIterator __last) {
-  typedef typename iterator_traits<_ForwardIterator>::value_type __v;
-  return std::unique(__first, __last, __equal_to<__v>());
+  return std::unique(__first, __last, __equal_to());
 }
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/__algorithm/unique_copy.h b/libcxx/include/__algorithm/unique_copy.h
index e33d795ecfdc8..81fcd50f011d5 100644
--- a/libcxx/include/__algorithm/unique_copy.h
+++ b/libcxx/include/__algorithm/unique_copy.h
@@ -114,8 +114,7 @@ unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __res
 template <class _InputIterator, class _OutputIterator>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
 unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
-  typedef typename iterator_traits<_InputIterator>::value_type __v;
-  return std::unique_copy(std::move(__first), std::move(__last), std::move(__result), __equal_to<__v>());
+  return std::unique_copy(std::move(__first), std::move(__last), std::move(__result), __equal_to());
 }
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/forward_list b/libcxx/include/forward_list
index 51643e9e2828c..61dde8167dfcd 100644
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -845,7 +845,7 @@ public:
     __remove_return_type remove(const value_type& __v);
     template <class _Predicate> __remove_return_type remove_if(_Predicate __pred);
     _LIBCPP_INLINE_VISIBILITY
-    __remove_return_type unique() {return unique(__equal_to<value_type>());}
+    __remove_return_type unique() { return unique(__equal_to()); }
     template <class _BinaryPredicate> __remove_return_type unique(_BinaryPredicate __binary_pred);
 #ifndef _LIBCPP_CXX03_LANG
     _LIBCPP_INLINE_VISIBILITY

diff  --git a/libcxx/include/list b/libcxx/include/list
index 4d68c5e72668b..a0c732739ca28 100644
--- a/libcxx/include/list
+++ b/libcxx/include/list
@@ -1063,7 +1063,7 @@ public:
     __remove_return_type remove(const value_type& __x);
     template <class _Pred> __remove_return_type remove_if(_Pred __pred);
     _LIBCPP_INLINE_VISIBILITY
-    __remove_return_type unique() { return unique(__equal_to<value_type>()); }
+    __remove_return_type unique() { return unique(__equal_to()); }
     template <class _BinaryPred>
         __remove_return_type unique(_BinaryPred __binary_pred);
     _LIBCPP_INLINE_VISIBILITY

diff  --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp
index 2b13bee2a806e..dfa425d974df9 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp
@@ -24,6 +24,24 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 
+template <class Iter1, class Iter2 = Iter1>
+void test_equal() {
+  int a[]          = {0, 1, 2, 3, 4, 5};
+  const unsigned s = sizeof(a) / sizeof(a[0]);
+  int b[s]         = {0, 1, 2, 5, 4, 5};
+
+  assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a)));
+  assert(std::equal(Iter2(a), Iter2(a + s), Iter1(a)));
+  assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b)));
+
+#if TEST_STD_VER >= 14
+  assert(std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s)));
+  assert(std::equal(Iter2(a), Iter2(a + s), Iter1(a), Iter1(a + s)));
+  assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(a), Iter2(a + s - 1)));
+  assert(!std::equal(Iter1(a), Iter1(a + s), Iter2(b), Iter2(b + s)));
+#endif
+}
+
 #if TEST_STD_VER > 17
 TEST_CONSTEXPR bool test_constexpr() {
     int ia[] = {1, 3, 6, 7};
@@ -46,44 +64,20 @@ TEST_CONSTEXPR bool test_constexpr() {
 
 int main(int, char**)
 {
-    int ia[] = {0, 1, 2, 3, 4, 5};
-    const unsigned s = sizeof(ia)/sizeof(ia[0]);
-    int ib[s] = {0, 1, 2, 5, 4, 5};
-    assert(std::equal(cpp17_input_iterator<const int*>(ia),
-                      cpp17_input_iterator<const int*>(ia+s),
-                      cpp17_input_iterator<const int*>(ia)));
-#if TEST_STD_VER >= 14
-    assert(std::equal(cpp17_input_iterator<const int*>(ia),
-                      cpp17_input_iterator<const int*>(ia+s),
-                      cpp17_input_iterator<const int*>(ia),
-                      cpp17_input_iterator<const int*>(ia+s)));
-    assert(std::equal(random_access_iterator<const int*>(ia),
-                      random_access_iterator<const int*>(ia+s),
-                      random_access_iterator<const int*>(ia),
-                      random_access_iterator<const int*>(ia+s)));
-#endif
-    assert(!std::equal(cpp17_input_iterator<const int*>(ia),
-                       cpp17_input_iterator<const int*>(ia+s),
-                       cpp17_input_iterator<const int*>(ib)));
-#if TEST_STD_VER >= 14
-    assert(!std::equal(cpp17_input_iterator<const int*>(ia),
-                       cpp17_input_iterator<const int*>(ia+s),
-                       cpp17_input_iterator<const int*>(ib),
-                       cpp17_input_iterator<const int*>(ib+s)));
-    assert(!std::equal(random_access_iterator<const int*>(ia),
-                       random_access_iterator<const int*>(ia+s),
-                       random_access_iterator<const int*>(ib),
-                       random_access_iterator<const int*>(ib+s)));
-    assert(!std::equal(cpp17_input_iterator<const int*>(ia),
-                       cpp17_input_iterator<const int*>(ia+s),
-                       cpp17_input_iterator<const int*>(ia),
-                       cpp17_input_iterator<const int*>(ia+s-1)));
-    assert(!std::equal(random_access_iterator<const int*>(ia),
-                       random_access_iterator<const int*>(ia+s),
-                       random_access_iterator<const int*>(ia),
-                       random_access_iterator<const int*>(ia+s-1)));
+  test_equal<cpp17_input_iterator<const int*> >();
+  test_equal<random_access_iterator<const int*> >();
 
-#endif
+  // Test all combinations of cv-qualifiers:
+  test_equal<int*>();
+  test_equal<int*, const int*>();
+  test_equal<int*, volatile int*>();
+  test_equal<int*, const volatile int*>();
+  test_equal<const int*>();
+  test_equal<const int*, volatile int*>();
+  test_equal<const int*, const volatile int*>();
+  test_equal<volatile int*>();
+  test_equal<volatile int*, const volatile int*>();
+  test_equal<const volatile int*>();
 
 #if TEST_STD_VER > 17
     static_assert(test_constexpr());


        


More information about the libcxx-commits mailing list