diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h index 3e81bca0348..05894b58002 100644 --- a/libstdc++-v3/include/bits/algorithmfwd.h +++ b/libstdc++-v3/include/bits/algorithmfwd.h @@ -315,10 +315,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION includes(_IIter1, _IIter1, _IIter2, _IIter2, _Compare); template + _GLIBCXX26_CONSTEXPR void inplace_merge(_BIter, _BIter, _BIter); template + _GLIBCXX26_CONSTEXPR void inplace_merge(_BIter, _BIter, _BIter, _Compare); diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index d3644a83f80..2814d90061c 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -2598,6 +2598,7 @@ namespace ranges typename _Comp = ranges::less, typename _Proj = identity> requires sortable<_Iter, _Comp, _Proj> + _GLIBCXX26_CONSTEXPR _Iter operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const @@ -2611,6 +2612,7 @@ namespace ranges template requires sortable, _Comp, _Proj> + _GLIBCXX26_CONSTEXPR borrowed_iterator_t<_Range> operator()(_Range&& __r, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index c3fea76014c..bb7dbfbd8e0 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -2465,6 +2465,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) } template + _GLIBCXX26_CONSTEXPR void __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, @@ -2483,6 +2484,12 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) const _DistanceType __len2 = std::distance(__middle, __last); #if _GLIBCXX_HOSTED +# if __glibcxx_constexpr_algorithms >= 202306L // >= C++26 + if consteval { + return std::__merge_without_buffer + (__first, __middle, __last, __len1, __len2, __comp); + } +# endif typedef _Temporary_buffer<_BidirectionalIterator, _ValueType> _TmpBuf; // __merge_adaptive will use a buffer for the smaller of // [first,middle) and [middle,last). @@ -2523,6 +2530,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) * distance(__first,__last). */ template + _GLIBCXX26_CONSTEXPR inline void inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, @@ -2564,6 +2572,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) * the function used for the initial sort. */ template + _GLIBCXX26_CONSTEXPR inline void inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, diff --git a/libstdc++-v3/testsuite/25_algorithms/headers/algorithm/synopsis.cc b/libstdc++-v3/testsuite/25_algorithms/headers/algorithm/synopsis.cc index 5000b18fc42..8d5c1fb7ac7 100644 --- a/libstdc++-v3/testsuite/25_algorithms/headers/algorithm/synopsis.cc +++ b/libstdc++-v3/testsuite/25_algorithms/headers/algorithm/synopsis.cc @@ -458,10 +458,12 @@ namespace std merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); template + _GLIBCXX26_CONSTEXPR void inplace_merge(_BIter, _BIter, _BIter); template + _GLIBCXX26_CONSTEXPR void inplace_merge(_BIter, _BIter, _BIter, _Compare); diff --git a/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constexpr.cc b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constexpr.cc new file mode 100644 index 00000000000..0bc4ed463d0 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constexpr.cc @@ -0,0 +1,72 @@ +// { dg-do compile { target c++26 } } + +#include +#include +#include +#include + +// returns a pair [array, index of partitioning point] +constexpr auto +create_array() +{ + return std::make_pair( + std::to_array({0, 2, 2, 2, 4, 6, 1, 2, 3, 3, 4, 4, 5}), + 6); +} + +constexpr bool +test01() +{ + auto [ar, index] = create_array(); + std::inplace_merge(ar.begin(), ar.begin() + index, ar.end()); + return std::is_sorted(ar.begin(), ar.end()); +} + +static_assert(test01()); + +constexpr bool +test02() +{ + auto [ar, index] = create_array(); + auto index_it = ar.begin() + index; + std::reverse(ar.begin(), index_it); + std::reverse(index_it, ar.end()); + std::inplace_merge(ar.begin(), index_it, ar.end(), std::greater<>()); + return std::is_sorted(ar.begin(), ar.end(), std::greater<>()); +} + +static_assert(test02()); + +constexpr bool +test03() +{ + auto [ar, index] = create_array(); + std::ranges::inplace_merge(ar, ar.begin() + index); + return std::ranges::is_sorted(ar); +} + +static_assert(test03()); + +constexpr bool +test04() +{ + auto [ar, index] = create_array(); + auto index_it = ar.begin() + index; + std::ranges::reverse(ar.begin(), index_it); + std::ranges::reverse(index_it, ar.end()); + std::ranges::inplace_merge(ar, index_it, std::ranges::greater()); + return std::ranges::is_sorted(ar, std::ranges::greater()); +} + +static_assert(test04()); + +constexpr bool +test05() +{ + auto [ar, index] = create_array(); + auto proj = [](int i) { return -i; }; + std::ranges::inplace_merge(ar, ar.begin() + index, std::ranges::greater(), proj); + return std::ranges::is_sorted(ar, std::ranges::greater(), proj); +} + +static_assert(test05());