[libcxx-commits] [libcxx] [libc++] Refactor swap_ranges dispatching (PR #173384)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Dec 23 06:39:47 PST 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/173384
>From 3e807430ac1acc4127763bccdade8dbcad49e4b8 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 23 Dec 2025 15:37:52 +0100
Subject: [PATCH] [libc++] Refactor swap_ranges dispatching
---
.../include/__algorithm/ranges_swap_ranges.h | 24 ++-
.../__algorithm/specialized_algorithms.h | 1 +
libcxx/include/__algorithm/swap_ranges.h | 199 ++----------------
libcxx/include/__bit_reference | 149 +++++++++++++
4 files changed, 194 insertions(+), 179 deletions(-)
diff --git a/libcxx/include/__algorithm/ranges_swap_ranges.h b/libcxx/include/__algorithm/ranges_swap_ranges.h
index ab6db50d8a13e..4e0df30587161 100644
--- a/libcxx/include/__algorithm/ranges_swap_ranges.h
+++ b/libcxx/include/__algorithm/ranges_swap_ranges.h
@@ -11,6 +11,7 @@
#include <__algorithm/in_in_result.h>
#include <__algorithm/iterator_operations.h>
+#include <__algorithm/min.h>
#include <__algorithm/swap_ranges.h>
#include <__config>
#include <__iterator/concepts.h>
@@ -41,9 +42,26 @@ struct __swap_ranges {
requires indirectly_swappable<_I1, _I2>
_LIBCPP_HIDE_FROM_ABI constexpr swap_ranges_result<_I1, _I2>
operator()(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2) const {
- auto __ret = std::__swap_ranges<_RangeAlgPolicy>(
- std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2));
- return {std::move(__ret.first), std::move(__ret.second)};
+ if constexpr (sized_sentinel_for<_I1, _S1> && sized_sentinel_for<_I2, _S2> &&
+ (random_access_iterator<_I1> || random_access_iterator<_I2>)) {
+ auto __offset = std::min(__last1 - __first1, __last2 - __first2);
+
+ if constexpr (random_access_iterator<_I1>) {
+ auto __ret = std::__swap_ranges<_RangeAlgPolicy>(__first1, __first1 + __offset, std::move(__first2));
+ return {std::move(__ret.first), std::move(__ret.second)};
+ } else {
+ auto __ret = std::__swap_ranges<_RangeAlgPolicy>(__first2, __first2 + __offset, std::move(__first1));
+ return {std::move(__ret.first), std::move(__ret.second)};
+ }
+ } else {
+ while (__first1 != __last1 && __first2 != __last2) {
+ ranges::iter_swap(__first1, __first2);
+ ++__first1;
+ ++__first2;
+ }
+
+ return {std::move(__first1), std::move(__first2)};
+ }
}
template <input_range _R1, input_range _R2>
diff --git a/libcxx/include/__algorithm/specialized_algorithms.h b/libcxx/include/__algorithm/specialized_algorithms.h
index 7cb94c015f767..58b4d93ee6894 100644
--- a/libcxx/include/__algorithm/specialized_algorithms.h
+++ b/libcxx/include/__algorithm/specialized_algorithms.h
@@ -21,6 +21,7 @@ namespace _Algorithm {
struct __copy {};
struct __fill_n {};
struct __for_each {};
+struct __swap_ranges {};
} // namespace _Algorithm
template <class>
diff --git a/libcxx/include/__algorithm/swap_ranges.h b/libcxx/include/__algorithm/swap_ranges.h
index 2731d4feaa63d..f81d9da2c13be 100644
--- a/libcxx/include/__algorithm/swap_ranges.h
+++ b/libcxx/include/__algorithm/swap_ranges.h
@@ -10,12 +10,10 @@
#define _LIBCPP___ALGORITHM_SWAP_RANGES_H
#include <__algorithm/iterator_operations.h>
-#include <__algorithm/min.h>
+#include <__algorithm/specialized_algorithms.h>
#include <__config>
-#include <__fwd/bit_reference.h>
#include <__utility/move.h>
#include <__utility/pair.h>
-#include <__utility/swap.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -26,189 +24,38 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _Cl, class _Cr>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cr, false> __swap_ranges_aligned(
- __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
- using _I1 = __bit_iterator<_Cl, false>;
- using difference_type = typename _I1::difference_type;
- using __storage_type = typename _I1::__storage_type;
-
- const int __bits_per_word = _I1::__bits_per_word;
- difference_type __n = __last - __first;
- if (__n > 0) {
- // do first word
- if (__first.__ctz_ != 0) {
- unsigned __clz = __bits_per_word - __first.__ctz_;
- difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
- __n -= __dn;
- __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
- __storage_type __b1 = *__first.__seg_ & __m;
- *__first.__seg_ &= ~__m;
- __storage_type __b2 = *__result.__seg_ & __m;
- *__result.__seg_ &= ~__m;
- *__result.__seg_ |= __b1;
- *__first.__seg_ |= __b2;
- __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
- __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
- ++__first.__seg_;
- // __first.__ctz_ = 0;
- }
- // __first.__ctz_ == 0;
- // do middle words
- for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_)
- swap(*__first.__seg_, *__result.__seg_);
- // do last word
- if (__n > 0) {
- __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
- __storage_type __b1 = *__first.__seg_ & __m;
- *__first.__seg_ &= ~__m;
- __storage_type __b2 = *__result.__seg_ & __m;
- *__result.__seg_ &= ~__m;
- *__result.__seg_ |= __b1;
- *__first.__seg_ |= __b2;
- __result.__ctz_ = static_cast<unsigned>(__n);
- }
- }
- return __result;
-}
-
-template <class _Cl, class _Cr>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cr, false> __swap_ranges_unaligned(
- __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
- using _I1 = __bit_iterator<_Cl, false>;
- using difference_type = typename _I1::difference_type;
- using __storage_type = typename _I1::__storage_type;
-
- const int __bits_per_word = _I1::__bits_per_word;
- difference_type __n = __last - __first;
- if (__n > 0) {
- // do first word
- if (__first.__ctz_ != 0) {
- unsigned __clz_f = __bits_per_word - __first.__ctz_;
- difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
- __n -= __dn;
- __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
- __storage_type __b1 = *__first.__seg_ & __m;
- *__first.__seg_ &= ~__m;
- unsigned __clz_r = __bits_per_word - __result.__ctz_;
- __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
- __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
- __storage_type __b2 = *__result.__seg_ & __m;
- *__result.__seg_ &= ~__m;
- if (__result.__ctz_ > __first.__ctz_) {
- unsigned __s = __result.__ctz_ - __first.__ctz_;
- *__result.__seg_ |= __b1 << __s;
- *__first.__seg_ |= __b2 >> __s;
- } else {
- unsigned __s = __first.__ctz_ - __result.__ctz_;
- *__result.__seg_ |= __b1 >> __s;
- *__first.__seg_ |= __b2 << __s;
- }
- __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
- __result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
- __dn -= __ddn;
- if (__dn > 0) {
- __m = ~__storage_type(0) >> (__bits_per_word - __dn);
- __b2 = *__result.__seg_ & __m;
- *__result.__seg_ &= ~__m;
- unsigned __s = __first.__ctz_ + __ddn;
- *__result.__seg_ |= __b1 >> __s;
- *__first.__seg_ |= __b2 << __s;
- __result.__ctz_ = static_cast<unsigned>(__dn);
- }
- ++__first.__seg_;
- // __first.__ctz_ = 0;
- }
- // __first.__ctz_ == 0;
- // do middle words
- __storage_type __m = ~__storage_type(0) << __result.__ctz_;
- unsigned __clz_r = __bits_per_word - __result.__ctz_;
- for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
- __storage_type __b1 = *__first.__seg_;
- __storage_type __b2 = *__result.__seg_ & __m;
- *__result.__seg_ &= ~__m;
- *__result.__seg_ |= __b1 << __result.__ctz_;
- *__first.__seg_ = __b2 >> __result.__ctz_;
- ++__result.__seg_;
- __b2 = *__result.__seg_ & ~__m;
- *__result.__seg_ &= __m;
- *__result.__seg_ |= __b1 >> __clz_r;
- *__first.__seg_ |= __b2 << __clz_r;
- }
- // do last word
- if (__n > 0) {
- __m = ~__storage_type(0) >> (__bits_per_word - __n);
- __storage_type __b1 = *__first.__seg_ & __m;
- *__first.__seg_ &= ~__m;
- __storage_type __dn = std::min<__storage_type>(__n, __clz_r);
- __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
- __storage_type __b2 = *__result.__seg_ & __m;
- *__result.__seg_ &= ~__m;
- *__result.__seg_ |= __b1 << __result.__ctz_;
- *__first.__seg_ |= __b2 >> __result.__ctz_;
- __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
- __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
- __n -= __dn;
- if (__n > 0) {
- __m = ~__storage_type(0) >> (__bits_per_word - __n);
- __b2 = *__result.__seg_ & __m;
- *__result.__seg_ &= ~__m;
- *__result.__seg_ |= __b1 >> __dn;
- *__first.__seg_ |= __b2 << __dn;
- __result.__ctz_ = static_cast<unsigned>(__n);
- }
- }
- }
- return __result;
-}
-
// 2+1 iterators: size2 >= size1; used by std::swap_ranges.
-template <class, class _Cl, class _Cr>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cl, false>, __bit_iterator<_Cr, false> >
-__swap_ranges(__bit_iterator<_Cl, false> __first1,
- __bit_iterator<_Cl, false> __last1,
- __bit_iterator<_Cr, false> __first2) {
- if (__first1.__ctz_ == __first2.__ctz_)
- return std::make_pair(__last1, std::__swap_ranges_aligned(__first1, __last1, __first2));
- return std::make_pair(__last1, std::__swap_ranges_unaligned(__first1, __last1, __first2));
-}
-
-// 2+2 iterators: used by std::ranges::swap_ranges.
-template <class _AlgPolicy, class _Cl, class _Cr>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cl, false>, __bit_iterator<_Cr, false> >
-__swap_ranges(__bit_iterator<_Cl, false> __first1,
- __bit_iterator<_Cl, false> __last1,
- __bit_iterator<_Cr, false> __first2,
- __bit_iterator<_Cr, false> __last2) {
- if (__last1 - __first1 < __last2 - __first2)
- return std::make_pair(__last1, std::__swap_ranges<_AlgPolicy>(__first1, __last1, __first2).second);
- return std::make_pair(std::__swap_ranges<_AlgPolicy>(__first2, __last2, __first1).second, __last2);
-}
-
-// 2+2 iterators: the shorter size will be used.
-template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _ForwardIterator2, class _Sentinel2>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator1, _ForwardIterator2>
-__swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _Sentinel2 __last2) {
- while (__first1 != __last1 && __first2 != __last2) {
- _IterOps<_AlgPolicy>::iter_swap(__first1, __first2);
- ++__first1;
- ++__first2;
- }
-
- return pair<_ForwardIterator1, _ForwardIterator2>(std::move(__first1), std::move(__first2));
+template <
+ class _AlgPolicy,
+ class _Iter1,
+ class _Sent1,
+ class _Iter2,
+ class _SpecialAlg =
+ __specialized_algorithm<_Algorithm::__swap_ranges, __iterator_pair<_Iter1, _Sent1>, __single_iterator<_Iter2> >,
+ __enable_if_t<_SpecialAlg::__has_algorithm, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2>
+__swap_ranges(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2) {
+ return _SpecialAlg()(std::move(__first1), std::move(__last1), std::move(__first2));
}
// 2+1 iterators: size2 >= size1.
-template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _ForwardIterator2>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator1, _ForwardIterator2>
-__swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2) {
+template <
+ class _AlgPolicy,
+ class _Iter1,
+ class _Sent1,
+ class _Iter2,
+ class _SpecialAlg =
+ __specialized_algorithm<_Algorithm::__swap_ranges, __iterator_pair<_Iter1, _Sent1>, __single_iterator<_Iter2> >,
+ __enable_if_t<!_SpecialAlg::__has_algorithm, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2>
+__swap_ranges(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2) {
while (__first1 != __last1) {
_IterOps<_AlgPolicy>::iter_swap(__first1, __first2);
++__first1;
++__first2;
}
- return pair<_ForwardIterator1, _ForwardIterator2>(std::move(__first1), std::move(__first2));
+ return pair<_Iter1, _Iter2>(std::move(__first1), std::move(__first2));
}
template <class _ForwardIterator1, class _ForwardIterator2>
diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference
index 8daf3a2baafcd..ed179d03618f5 100644
--- a/libcxx/include/__bit_reference
+++ b/libcxx/include/__bit_reference
@@ -728,6 +728,155 @@ struct __specialized_algorithm<_Algorithm::__copy,
}
};
+template <class _Cl, class _Cr>
+struct __specialized_algorithm<_Algorithm::__swap_ranges,
+ __iterator_pair<__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false> >,
+ __single_iterator<__bit_iterator<_Cr, false> > > {
+ _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cr, false> __aligned_impl(
+ __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
+ using _I1 = __bit_iterator<_Cl, false>;
+ using difference_type = typename _I1::difference_type;
+ using __storage_type = typename _I1::__storage_type;
+
+ const int __bits_per_word = _I1::__bits_per_word;
+ difference_type __n = __last - __first;
+ if (__n > 0) {
+ // do first word
+ if (__first.__ctz_ != 0) {
+ unsigned __clz = __bits_per_word - __first.__ctz_;
+ difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
+ __n -= __dn;
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
+ __storage_type __b1 = *__first.__seg_ & __m;
+ *__first.__seg_ &= ~__m;
+ __storage_type __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b1;
+ *__first.__seg_ |= __b2;
+ __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
+ __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
+ ++__first.__seg_;
+ // __first.__ctz_ = 0;
+ }
+ // __first.__ctz_ == 0;
+ // do middle words
+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_)
+ swap(*__first.__seg_, *__result.__seg_);
+ // do last word
+ if (__n > 0) {
+ __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __storage_type __b1 = *__first.__seg_ & __m;
+ *__first.__seg_ &= ~__m;
+ __storage_type __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b1;
+ *__first.__seg_ |= __b2;
+ __result.__ctz_ = static_cast<unsigned>(__n);
+ }
+ }
+ return __result;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cr, false> __unaligned_impl(
+ __bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
+ using _I1 = __bit_iterator<_Cl, false>;
+ using difference_type = typename _I1::difference_type;
+ using __storage_type = typename _I1::__storage_type;
+
+ const int __bits_per_word = _I1::__bits_per_word;
+ difference_type __n = __last - __first;
+ if (__n > 0) {
+ // do first word
+ if (__first.__ctz_ != 0) {
+ unsigned __clz_f = __bits_per_word - __first.__ctz_;
+ difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
+ __n -= __dn;
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
+ __storage_type __b1 = *__first.__seg_ & __m;
+ *__first.__seg_ &= ~__m;
+ unsigned __clz_r = __bits_per_word - __result.__ctz_;
+ __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
+ __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
+ __storage_type __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ if (__result.__ctz_ > __first.__ctz_) {
+ unsigned __s = __result.__ctz_ - __first.__ctz_;
+ *__result.__seg_ |= __b1 << __s;
+ *__first.__seg_ |= __b2 >> __s;
+ } else {
+ unsigned __s = __first.__ctz_ - __result.__ctz_;
+ *__result.__seg_ |= __b1 >> __s;
+ *__first.__seg_ |= __b2 << __s;
+ }
+ __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
+ __result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
+ __dn -= __ddn;
+ if (__dn > 0) {
+ __m = ~__storage_type(0) >> (__bits_per_word - __dn);
+ __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ unsigned __s = __first.__ctz_ + __ddn;
+ *__result.__seg_ |= __b1 >> __s;
+ *__first.__seg_ |= __b2 << __s;
+ __result.__ctz_ = static_cast<unsigned>(__dn);
+ }
+ ++__first.__seg_;
+ // __first.__ctz_ = 0;
+ }
+ // __first.__ctz_ == 0;
+ // do middle words
+ __storage_type __m = ~__storage_type(0) << __result.__ctz_;
+ unsigned __clz_r = __bits_per_word - __result.__ctz_;
+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
+ __storage_type __b1 = *__first.__seg_;
+ __storage_type __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b1 << __result.__ctz_;
+ *__first.__seg_ = __b2 >> __result.__ctz_;
+ ++__result.__seg_;
+ __b2 = *__result.__seg_ & ~__m;
+ *__result.__seg_ &= __m;
+ *__result.__seg_ |= __b1 >> __clz_r;
+ *__first.__seg_ |= __b2 << __clz_r;
+ }
+ // do last word
+ if (__n > 0) {
+ __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __storage_type __b1 = *__first.__seg_ & __m;
+ *__first.__seg_ &= ~__m;
+ __storage_type __dn = std::min<__storage_type>(__n, __clz_r);
+ __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
+ __storage_type __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b1 << __result.__ctz_;
+ *__first.__seg_ |= __b2 >> __result.__ctz_;
+ __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
+ __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
+ __n -= __dn;
+ if (__n > 0) {
+ __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b1 >> __dn;
+ *__first.__seg_ |= __b2 << __dn;
+ __result.__ctz_ = static_cast<unsigned>(__n);
+ }
+ }
+ }
+ return __result;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI static
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cl, false>, __bit_iterator<_Cr, false> >
+ operator()(__bit_iterator<_Cl, false> __first1,
+ __bit_iterator<_Cl, false> __last1,
+ __bit_iterator<_Cr, false> __first2) {
+ if (__first1.__ctz_ == __first2.__ctz_)
+ return std::make_pair(__last1, __aligned_impl(__first1, __last1, __first2));
+ return std::make_pair(__last1, __unaligned_impl(__first1, __last1, __first2));
+ }
+};
+
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
More information about the libcxx-commits
mailing list