diff --git a/include/cpp-sort/adapters/container_aware_adapter.h b/include/cpp-sort/adapters/container_aware_adapter.h index 4f22ef6b..6dc1f08a 100644 --- a/include/cpp-sort/adapters/container_aware_adapter.h +++ b/include/cpp-sort/adapters/container_aware_adapter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Morwenn + * Copyright (c) 2016-2024 Morwenn * SPDX-License-Identifier: MIT */ #ifndef CPPSORT_ADAPTERS_CONTAINER_AWARE_ADAPTER_H_ @@ -30,21 +30,22 @@ namespace cppsort struct adl_despair { template - auto operator()(Sorter sorter, Collection& collection) const + auto operator()(this auto&&, Sorter sorter, Collection& collection) -> decltype(sort(std::move(sorter), collection)) { return sort(std::move(sorter), collection); } template - auto operator()(Sorter sorter, Collection& collection, Function function) const + auto operator()(this auto&&, Sorter sorter, Collection& collection, Function function) -> decltype(sort(std::move(sorter), collection, std::move(function))) { return sort(std::move(sorter), collection, std::move(function)); } template - auto operator()(Sorter sorter, Collection& collection, Compare compare, Projection projection) const + auto operator()(this auto&&, Sorter sorter, Collection& collection, + Compare compare, Projection projection) -> decltype(sort(std::move(sorter), collection, std::move(compare), std::move(projection))) { @@ -100,225 +101,318 @@ namespace cppsort template< bool Stability = false, + typename Self, typename Collection > - requires detail::can_sort::value - auto operator()(Collection& collection) const + requires detail::can_sort< + copy_cvref_t, + Collection + >::value + auto operator()(this Self&& self, Collection& collection) -> mstd::conditional_t< Stability, std::false_type, - decltype(detail::adl_despair{}(this->get(), collection)) + decltype(detail::adl_despair{}(std::forward(self).get(), collection)) > { - return detail::adl_despair{}(this->get(), collection); + return detail::adl_despair{}(std::forward(self).get(), collection); } template< bool Stability = false, + typename Self, typename Collection > - requires (not detail::can_sort::value) - auto operator()(Collection& collection) const + requires ( + not detail::can_sort< + copy_cvref_t, + Collection + >::value + ) + auto operator()(this Self&& self, Collection& collection) -> mstd::conditional_t< Stability, cppsort::is_stable, - decltype(this->get()(collection)) + decltype(std::forward(self).get()(collection)) > { - return this->get()(collection); + return std::forward(self).get()(collection); } template< bool Stability = false, + typename Self, typename Collection, typename Compare > - requires detail::can_comparison_sort::value - auto operator()(Collection& collection, Compare compare) const + requires detail::can_comparison_sort< + copy_cvref_t, + Collection, + Compare + >::value + auto operator()(this Self&& self, Collection& collection, Compare compare) -> mstd::conditional_t< Stability, std::false_type, - decltype(detail::adl_despair{}(this->get(), collection, std::move(compare))) + decltype(detail::adl_despair{}( + std::forward(self).get(), collection, std::move(compare))) > { - return detail::adl_despair{}(this->get(), collection, std::move(compare)); + return detail::adl_despair{}(std::forward(self).get(), collection, std::move(compare)); } template< bool Stability = false, + typename Self, typename Collection, typename Compare > requires ( not is_projection_v && - not detail::can_comparison_sort::value + not detail::can_comparison_sort< + copy_cvref_t, + Collection, + Compare + >::value ) - auto operator()(Collection& collection, Compare compare) const + auto operator()(this Self&& self, Collection& collection, Compare compare) -> mstd::conditional_t< Stability, cppsort::is_stable, - decltype(this->get()(collection, std::move(compare))) + decltype(std::forward(self).get()(collection, std::move(compare))) > { - return this->get()(collection, std::move(compare)); + return std::forward(self).get()(collection, std::move(compare)); } template< bool Stability = false, + typename Self, typename Collection, typename Projection > requires ( - not detail::can_comparison_sort::value && - detail::can_projection_sort::value + not detail::can_comparison_sort< + copy_cvref_t, + Collection, + Projection + >::value && + detail::can_projection_sort< + copy_cvref_t, + Collection, + Projection + >::value ) - auto operator()(Collection& collection, Projection projection) const + auto operator()(this Self&& self, Collection& collection, Projection projection) -> mstd::conditional_t< Stability, std::false_type, - decltype(detail::adl_despair{}(this->get(), collection, std::move(projection))) + decltype(detail::adl_despair{}( + std::forward(self).get(), collection, std::move(projection))) > { - return detail::adl_despair{}(this->get(), collection, std::move(projection)); + return detail::adl_despair{}( + std::forward(self).get(), collection, std::move(projection)); } template< bool Stability = false, + typename Self, typename Collection, typename Projection > requires ( - not detail::can_projection_sort::value && - detail::can_comparison_projection_sort, Projection>::value + not detail::can_projection_sort< + copy_cvref_t, + Collection, + Projection + >::value && + detail::can_comparison_projection_sort< + copy_cvref_t, + Collection, + std::less<>, + Projection + >::value ) - auto operator()(Collection& collection, Projection projection) const + auto operator()(this Self&& self, Collection& collection, Projection projection) -> mstd::conditional_t< Stability, std::false_type, - decltype(detail::adl_despair{}(this->get(), collection, std::less{}, std::move(projection))) + decltype(detail::adl_despair{}( + std::forward(self).get(), collection, std::less{}, std::move(projection))) > { - return detail::adl_despair{}(this->get(), collection, std::less{}, std::move(projection)); + return detail::adl_despair{}( + std::forward(self).get(), collection, std::less{}, std::move(projection)); } template< bool Stability = false, + typename Self, typename Collection, typename Projection > requires ( - not detail::can_projection_sort::value && - not detail::can_comparison_projection_sort, Projection>::value && + not detail::can_projection_sort< + copy_cvref_t, + Collection, + Projection + >::value && + not detail::can_comparison_projection_sort< + copy_cvref_t, + Collection, + std::less<>, + Projection + >::value && detail::can_comparison_sort< - Sorter, + copy_cvref_t, Collection, projection_compare_t, Projection> >::value ) - auto operator()(Collection& collection, Projection projection) const + auto operator()(this Self&& self, Collection& collection, Projection projection) -> mstd::conditional_t< Stability, std::false_type, - decltype(detail::adl_despair{}(this->get(), collection, - projection_compare(std::less{}, std::move(projection)))) + decltype(detail::adl_despair{}( + std::forward(self).get(), collection, + projection_compare(std::less{}, std::move(projection)))) > { - return detail::adl_despair{}(this->get(), collection, - projection_compare(std::less{}, std::move(projection))); + return detail::adl_despair{}( + std::forward(self).get(), collection, + projection_compare(std::less{}, std::move(projection))); } template< bool Stability = false, + typename Self, typename Collection, typename Projection > requires ( is_projection_v && - not detail::can_projection_sort::value && - not detail::can_comparison_projection_sort, Projection>::value && + not detail::can_projection_sort< + copy_cvref_t, + Collection, + Projection + >::value && + not detail::can_comparison_projection_sort< + copy_cvref_t, + Collection, + std::less<>, + Projection + >::value && not detail::can_comparison_sort< - Sorter, + copy_cvref_t, Collection, projection_compare_t, Projection> >::value ) - auto operator()(Collection& collection, Projection projection) const + auto operator()(this Self&& self, Collection& collection, Projection projection) -> mstd::conditional_t< Stability, cppsort::is_stable, - decltype(this->get()(collection, std::move(projection))) + decltype(std::forward(self).get()(collection, std::move(projection))) > { - return this->get()(collection, std::move(projection)); + return std::forward(self).get()(collection, std::move(projection)); } template< bool Stability = false, + typename Self, typename Collection, typename Compare, typename Projection > - requires detail::can_comparison_projection_sort::value - auto operator()(Collection& collection, Compare compare, Projection projection) const + requires detail::can_comparison_projection_sort< + copy_cvref_t, + Collection, + Compare, + Projection + >::value + auto operator()(this Self&& self, Collection& collection, + Compare compare, Projection projection) -> mstd::conditional_t< Stability, std::false_type, - decltype(detail::adl_despair{}(this->get(), collection, - std::move(compare), std::move(projection))) + decltype(detail::adl_despair{}( + std::forward(self).get(), collection, + std::move(compare), std::move(projection))) > { - return detail::adl_despair{}(this->get(), collection, - std::move(compare), std::move(projection)); + return detail::adl_despair{}( + std::forward(self).get(), collection, + std::move(compare), std::move(projection)); } template< bool Stability = false, + typename Self, typename Collection, typename Compare, typename Projection > requires ( - not detail::can_comparison_projection_sort::value && + not detail::can_comparison_projection_sort< + copy_cvref_t, + Collection, + Compare, + Projection + >::value && detail::can_comparison_sort< - Sorter, + copy_cvref_t, Collection, projection_compare_t >::value ) - auto operator()(Collection& collection, Compare compare, Projection projection) const + auto operator()(this Self&& self, Collection& collection, + Compare compare, Projection projection) -> mstd::conditional_t< Stability, std::false_type, - decltype(detail::adl_despair{}(this->get(), collection, - projection_compare(std::move(compare), std::move(projection)))) + decltype(detail::adl_despair{}( + std::forward(self).get(), collection, + projection_compare(std::move(compare), std::move(projection)))) > { - return detail::adl_despair{}(this->get(), collection, - projection_compare(std::move(compare), std::move(projection))); + return detail::adl_despair{}( + std::forward(self).get(), collection, + projection_compare(std::move(compare), std::move(projection))); } template< bool Stability = false, + typename Self, typename Collection, typename Compare, typename Projection > requires ( - not detail::can_comparison_projection_sort::value && + not detail::can_comparison_projection_sort< + copy_cvref_t, + Collection, + Compare, + Projection + >::value && not detail::can_comparison_sort< - Sorter, + copy_cvref_t, Collection, projection_compare_t >::value ) - auto operator()(Collection& collection, Compare compare, Projection projection) const + auto operator()(this Self&& self, Collection& collection, + Compare compare, Projection projection) -> mstd::conditional_t< Stability, cppsort::is_stable, - decltype(this->get()(collection, std::move(compare), std::move(projection))) + decltype(std::forward(self).get()( + collection, std::move(compare), std::move(projection))) > { - return this->get()(collection, std::move(compare), std::move(projection)); + return std::forward(self).get()( + collection, std::move(compare), std::move(projection)); } }; } diff --git a/include/cpp-sort/adapters/hybrid_adapter.h b/include/cpp-sort/adapters/hybrid_adapter.h index df5a3a8d..a24b871c 100644 --- a/include/cpp-sort/adapters/hybrid_adapter.h +++ b/include/cpp-sort/adapters/hybrid_adapter.h @@ -81,6 +81,8 @@ namespace cppsort struct hybrid_adapter_storage_leaf: utility::adapter_storage { + using base_class = utility::adapter_storage; + hybrid_adapter_storage_leaf() = default; constexpr hybrid_adapter_storage_leaf(Sorter&& sorter): @@ -91,11 +93,11 @@ namespace cppsort // preferred for its iterator category first, then for its // position into the sorters - template - constexpr auto operator()(choice, Args&&... args) const - -> decltype(this->get()(std::forward(args)...)) + template + constexpr auto operator()(this Self&& self, choice, Args&&... args) + -> decltype(std::forward(self).base_class::get()(std::forward(args)...)) { - return this->get()(std::forward(args)...); + return std::forward(self).base_class::get()(std::forward(args)...); } template @@ -209,15 +211,15 @@ namespace cppsort //////////////////////////////////////////////////////////// // Call operator - template - constexpr auto operator()(Range&& range, Args&&... args) const - -> decltype(base_class::operator()( + template + constexpr auto operator()(this Self&& self, Range&& range, Args&&... args) + -> decltype(std::forward(self).base_class::operator()( detail::choice_for_it, sizeof...(Sorters)>{}, std::forward(range), std::forward(args)... )) { - return base_class::operator()( + return std::forward(self).base_class::operator()( detail::choice_for_it, sizeof...(Sorters)>{}, std::forward(range), std::forward(args)... @@ -225,18 +227,19 @@ namespace cppsort } template< + typename Self, mstd::forward_iterator Iterator, mstd::sentinel_for Sentinel, typename... Args > - constexpr auto operator()(Iterator first, Sentinel last, Args&&... args) const - -> decltype(base_class::operator()( + constexpr auto operator()(this Self&& self, Iterator first, Sentinel last, Args&&... args) + -> decltype(std::forward(self).base_class::operator()( detail::choice_for_it{}, std::move(first), std::move(last), std::forward(args)... )) { - return base_class::operator()( + return std::forward(self).base_class::operator()( detail::choice_for_it{}, std::move(first), std::move(last), std::forward(args)... diff --git a/include/cpp-sort/adapters/indirect_adapter.h b/include/cpp-sort/adapters/indirect_adapter.h index f38ddfd0..4535932e 100644 --- a/include/cpp-sort/adapters/indirect_adapter.h +++ b/include/cpp-sort/adapters/indirect_adapter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2022 Morwenn + * Copyright (c) 2015-2024 Morwenn * SPDX-License-Identifier: MIT */ #ifndef CPPSORT_ADAPTERS_INDIRECT_ADAPTER_H_ @@ -134,36 +134,42 @@ namespace cppsort {} template< + typename Self, mstd::forward_range Range, typename Compare = std::less<>, typename Projection = std::identity > requires is_projection_v - auto operator()(Range&& range, Compare compare={}, Projection projection={}) const - -> decltype(sort_indirectly(this->get(), + auto operator()(this Self&& self, Range&& range, + Compare compare={}, Projection projection={}) + -> decltype(sort_indirectly(std::forward(self).get(), mstd::begin(range), mstd::end(range), mstd::distance(range), std::move(compare), std::move(projection))) { - return sort_indirectly(this->get(), + return sort_indirectly(std::forward(self).get(), mstd::begin(range), mstd::end(range), mstd::distance(range), std::move(compare), std::move(projection)); } template< + typename Self, mstd::forward_iterator Iterator, mstd::sentinel_for Sentinel, typename Compare = std::less<>, typename Projection = std::identity > requires is_projection_iterator_v - auto operator()(Iterator first, Sentinel last, Compare compare={}, Projection projection={}) const - -> decltype(sort_indirectly(this->get(), first, mstd::next(first, last), + auto operator()(this Self&& self, Iterator first, Sentinel last, + Compare compare={}, Projection projection={}) + -> decltype(sort_indirectly(std::forward(self).get(), + first, mstd::next(first, last), mstd::distance(first, last), std::move(compare), std::move(projection))) { - return sort_indirectly(this->get(), first, mstd::next(first, last), + return sort_indirectly(std::forward(self).get(), + first, mstd::next(first, last), mstd::distance(first, last), std::move(compare), std::move(projection)); } diff --git a/include/cpp-sort/adapters/out_of_place_adapter.h b/include/cpp-sort/adapters/out_of_place_adapter.h index b8234cf9..b16393dd 100644 --- a/include/cpp-sort/adapters/out_of_place_adapter.h +++ b/include/cpp-sort/adapters/out_of_place_adapter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2022 Morwenn + * Copyright (c) 2018-2024 Morwenn * SPDX-License-Identifier: MIT */ #ifndef CPPSORT_ADAPTERS_OUT_OF_PLACE_ADAPTER_H_ @@ -31,7 +31,7 @@ namespace cppsort { template auto sort_out_of_place(ForwardIterator first, ForwardIterator last, - Size size, const Sorter& sorter, Args&&... args) + Size size, Sorter&& sorter, Args&&... args) -> decltype(auto) { using rvalue_type = rvalue_type_t; @@ -47,7 +47,8 @@ namespace cppsort }); // Sort the elements in the memory buffer - return sorter(buffer.begin(), buffer.end(), std::forward(args)...); + return std::forward(sorter)(buffer.begin(), buffer.end(), + std::forward(args)...); } } @@ -73,26 +74,29 @@ namespace cppsort // Wrap and call the sorter template< + typename Self, mstd::forward_iterator Iterator, mstd::sentinel_for Sentinel, typename... Args > - auto operator()(Iterator first, Sentinel last, Args&&... args) const + auto operator()(this Self&& self, Iterator first, Sentinel last, Args&&... args) -> decltype(auto) { auto dist = mstd::distance(first, last); auto last_it = mstd::next(first, last); return detail::sort_out_of_place(std::move(first), std::move(last_it), dist, - this->get(), std::forward(args)...); + std::forward(self).get(), + std::forward(args)...); } - template - auto operator()(Range&& range, Args&&... args) const + template + auto operator()(this Self&& self, Range&& range, Args&&... args) -> decltype(auto) { auto dist = mstd::distance(range); return detail::sort_out_of_place(mstd::begin(range), mstd::end(range), dist, - this->get(), std::forward(args)...); + std::forward(self).get(), + std::forward(args)...); } //////////////////////////////////////////////////////////// diff --git a/include/cpp-sort/adapters/schwartz_adapter.h b/include/cpp-sort/adapters/schwartz_adapter.h index 9408522b..e0fa2f56 100644 --- a/include/cpp-sort/adapters/schwartz_adapter.h +++ b/include/cpp-sort/adapters/schwartz_adapter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Morwenn + * Copyright (c) 2016-2024 Morwenn * SPDX-License-Identifier: MIT */ #ifndef CPPSORT_ADAPTERS_SCHWARTZ_ADAPTER_H_ @@ -107,78 +107,93 @@ namespace cppsort {} template< + typename Self, mstd::forward_range Range, typename Compare = std::less<>, typename Projection = std::identity > requires is_projection_v - auto operator()(Range&& range, Compare compare, Projection projection) const + auto operator()(this Self&& self, Range&& range, Compare compare, Projection projection) -> decltype(auto) { return sort_with_schwartz(mstd::begin(range), mstd::distance(range), std::move(compare), std::move(projection), - this->get()); + std::forward(self).get()); } template< + typename Self, mstd::forward_iterator Iterator, mstd::sentinel_for Sentinel, typename Compare = std::less<>, typename Projection = std::identity > requires is_projection_iterator_v - auto operator()(Iterator first, Sentinel last, - Compare compare, Projection projection) const + auto operator()(this Self&& self, Iterator first, Sentinel last, + Compare compare, Projection projection) -> decltype(auto) { return sort_with_schwartz(first, mstd::distance(first, last), std::move(compare), std::move(projection), - this->get()); + std::forward(self).get()); } template< + typename Self, mstd::forward_range Range, typename Compare = std::less<> > requires (not is_projection_v) - auto operator()(Range&& range, Compare compare={}) const - -> decltype(this->get()(std::forward(range), std::move(compare))) + auto operator()(this Self&& self, Range&& range, Compare compare={}) + -> decltype(std::forward(self).get()( + std::forward(range), std::move(compare))) { // No projection to handle, forward everything to the adapted sorter - return this->get()(std::forward(range), std::move(compare)); + return std::forward(self).get()( + std::forward(range), std::move(compare)); } template< + typename Self, mstd::forward_iterator Iterator, mstd::sentinel_for Sentinel, typename Compare = std::less<> > requires (not is_projection_iterator_v) - auto operator()(Iterator first, Sentinel last, Compare compare={}) const - -> decltype(this->get()(std::move(first), std::move(last), std::move(compare))) + auto operator()(this Self&& self, Iterator first, Sentinel last, Compare compare={}) + -> decltype(std::forward(self).get()( + std::move(first), std::move(last), std::move(compare))) { // No projection to handle, forward everything to the adapted sorter - return this->get()(std::move(first), std::move(last), std::move(compare)); + return std::forward(self).get()( + std::move(first), std::move(last), std::move(compare)); } - template - auto operator()(Range&& range, Compare compare, std::identity projection) const - -> decltype(this->get()(std::forward(range), std::move(compare), projection)) + template + auto operator()(this Self&& self, Range&& range, + Compare compare, std::identity projection) + -> decltype(std::forward(self).get()( + std::forward(range), std::move(compare), projection)) { // std::identity does nothing, bypass schartz_adapter entirely - return this->get()(std::forward(range), std::move(compare), projection); + return std::forward(self).get()( + std::forward(range), std::move(compare), projection); } template< + typename Self, mstd::forward_iterator Iterator, mstd::sentinel_for Sentinel, typename Compare > - auto operator()(Iterator first, Sentinel last, Compare compare, std::identity projection) const - -> decltype(this->get()(std::move(first), std::move(last), std::move(compare), projection)) + auto operator()(this Self&& self, Iterator first, Sentinel last, + Compare compare, std::identity projection) + -> decltype(std::forward(self).get()( + std::move(first), std::move(last), std::move(compare), projection)) { // std::identity does nothing, bypass schartz_adapter entirely - return this->get()(std::move(first), std::move(last), std::move(compare), projection); + return std::forward(self).get()( + std::move(first), std::move(last), std::move(compare), projection); } }; } diff --git a/include/cpp-sort/adapters/self_sort_adapter.h b/include/cpp-sort/adapters/self_sort_adapter.h index 700852ba..901a9a7e 100644 --- a/include/cpp-sort/adapters/self_sort_adapter.h +++ b/include/cpp-sort/adapters/self_sort_adapter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2022 Morwenn + * Copyright (c) 2015-2024 Morwenn * SPDX-License-Identifier: MIT */ #ifndef CPPSORT_ADAPTERS_SELF_SORT_ADAPTER_H_ @@ -28,14 +28,14 @@ namespace cppsort template concept has_sort_method = - requires (Collection& collection, Args&&... args) { - collection.sort(std::forward(args)...); + requires (Collection&& collection, Args&&... args) { + std::forward(collection).sort(std::forward(args)...); }; template concept has_stable_sort_method = - requires (Collection& collection, Args&&... args) { - collection.stable_sort(std::forward(args)...); + requires (Collection&& collection, Args&&... args) { + std::forward(collection).stable_sort(std::forward(args)...); }; } @@ -65,7 +65,7 @@ namespace cppsort template requires detail::has_sort_method - auto operator()(Collection&& collection, Args&&... args) const + static auto operator()(Collection&& collection, Args&&... args) -> decltype(std::forward(collection).sort(utility::as_function(args)...)) { return std::forward(collection).sort(utility::as_function(args)...); @@ -76,30 +76,32 @@ namespace cppsort not detail::has_sort_method && detail::has_stable_sort_method ) - auto operator()(Collection&& collection, Args&&... args) const + static auto operator()(Collection&& collection, Args&&... args) -> decltype(std::forward(collection).stable_sort(utility::as_function(args)...)) { return std::forward(collection).stable_sort(utility::as_function(args)...); } - template + template requires ( not detail::has_sort_method && not detail::has_stable_sort_method ) - auto operator()(Collection&& collection, Args&&... args) const - -> decltype(this->get()(std::forward(collection), std::forward(args)...)) + auto operator()(this Self&& self, Collection&& collection, Args&&... args) + -> decltype(std::forward(self).get()( + std::forward(collection), std::forward(args)...)) { - return this->get()(std::forward(collection), std::forward(args)...); + return std::forward(self).get()( + std::forward(collection), std::forward(args)...); } - template - auto operator()(Iterator first, Iterator last, Args&&... args) const - -> decltype(this->get()(std::move(first), std::move(last), - std::forward(args)...)) + template + auto operator()(this Self&& self, Iterator first, Iterator last, Args&&... args) + -> decltype(std::forward(self).get()( + std::move(first), std::move(last), std::forward(args)...)) { - return this->get()(std::move(first), std::move(last), - std::forward(args)...); + return std::forward(self).get()( + std::move(first), std::move(last), std::forward(args)...); } //////////////////////////////////////////////////////////// diff --git a/include/cpp-sort/adapters/stable_adapter.h b/include/cpp-sort/adapters/stable_adapter.h index d0c14320..0b0e4c6d 100644 --- a/include/cpp-sort/adapters/stable_adapter.h +++ b/include/cpp-sort/adapters/stable_adapter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Morwenn + * Copyright (c) 2016-2024 Morwenn * SPDX-License-Identifier: MIT */ #ifndef CPPSORT_ADAPTERS_STABLE_ADAPTER_H_ @@ -128,34 +128,37 @@ namespace cppsort {} template< + typename Self, mstd::forward_range Range, typename Compare = std::less<>, typename Projection = std::identity > requires is_projection_v - auto operator()(Range&& range, Compare compare={}, Projection projection={}) const + auto operator()(this Self&& self, Range&& range, + Compare compare={}, Projection projection={}) -> decltype(auto) { return make_stable_and_sort(mstd::begin(range), mstd::distance(range), std::move(compare), std::move(projection), - this->get()); + std::forward(self).get()); } template< + typename Self, mstd::forward_iterator Iterator, mstd::sentinel_for Sentinel, typename Compare = std::less<>, typename Projection = std::identity > requires is_projection_iterator_v - auto operator()(Iterator first, Sentinel last, - Compare compare={}, Projection projection={}) const + auto operator()(this Self&& self, Iterator first, Sentinel last, + Compare compare={}, Projection projection={}) -> decltype(auto) { auto dist = mstd::distance(first, last); return make_stable_and_sort(std::move(first), dist, std::move(compare), std::move(projection), - this->get()); + std::forward(self).get()); } //////////////////////////////////////////////////////////// @@ -202,20 +205,20 @@ namespace cppsort utility::adapter_storage(std::move(sorter)) {} - template + template requires is_stable_v - auto operator()(Args&&... args) const - -> decltype(this->get()(std::forward(args)...)) + auto operator()(this Self&& self, Args&&... args) + -> decltype(std::forward(self).get()(std::forward(args)...)) { - return this->get()(std::forward(args)...); + return std::forward(self).get()(std::forward(args)...); } - template + template requires (not is_stable_v) - auto operator()(Args&&... args) const - -> decltype(make_stable(this->get())(std::forward(args)...)) + auto operator()(this Self&& self, Args&&... args) + -> decltype(make_stable(std::forward(self).get())(std::forward(args)...)) { - return make_stable(this->get())(std::forward(args)...); + return make_stable(std::forward(self).get())(std::forward(args)...); } //////////////////////////////////////////////////////////// diff --git a/include/cpp-sort/adapters/verge_adapter.h b/include/cpp-sort/adapters/verge_adapter.h index 8244748a..94a60447 100644 --- a/include/cpp-sort/adapters/verge_adapter.h +++ b/include/cpp-sort/adapters/verge_adapter.h @@ -38,12 +38,13 @@ namespace cppsort {} template< + typename Self, mstd::bidirectional_range Range, typename Compare = std::less<>, typename Projection = std::identity > requires is_projection_v - auto operator()(Range&& range, Compare compare={}, Projection projection={}) const + auto operator()(this Self&& self, Range&& range, Compare compare={}, Projection projection={}) -> mstd::iterator_t { static_assert( @@ -60,19 +61,20 @@ namespace cppsort verge::sort(std::move(first), last_it, mstd::distance(range), std::move(compare), std::move(projection), - this->get()); + std::forward(self).get()); return last_it; } template< + typename Self, mstd::bidirectional_iterator Iterator, mstd::sentinel_for Sentinel, typename Compare = std::less<>, typename Projection = std::identity > requires is_projection_iterator_v - auto operator()(Iterator first, Sentinel last, - Compare compare={}, Projection projection={}) const + auto operator()(this Self&& self, Iterator first, Sentinel last, + Compare compare={}, Projection projection={}) -> Iterator { static_assert( @@ -87,7 +89,7 @@ namespace cppsort auto last_it = mstd::next(first, std::move(last)); verge::sort(std::move(first), last_it, dist, std::move(compare), std::move(projection), - this->get()); + std::forward(self).get()); return last_it; } diff --git a/include/cpp-sort/utility/adapter_storage.h b/include/cpp-sort/utility/adapter_storage.h index ca6640d5..3ee7b085 100644 --- a/include/cpp-sort/utility/adapter_storage.h +++ b/include/cpp-sort/utility/adapter_storage.h @@ -81,7 +81,9 @@ namespace cppsort::utility constexpr auto get(this Self&& self) noexcept -> cppsort::detail::copy_cvref_t { - return std::forward(self).sorter; + return static_cast< + cppsort::detail::copy_cvref_t> + >(self).sorter; } }; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4b34fe38..ce096e22 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -118,6 +118,7 @@ add_executable(main-tests adapters/every_adapter_constexpr.cpp $<$>:adapters/every_adapter_fptr.cpp> adapters/every_adapter_internal_compare.cpp + adapters/every_adapter_mutable_sorter.cpp adapters/every_adapter_non_const_compare.cpp adapters/every_adapter_sentinel.cpp adapters/every_adapter_stateful_sorter.cpp diff --git a/tests/adapters/every_adapter_mutable_sorter.cpp b/tests/adapters/every_adapter_mutable_sorter.cpp new file mode 100644 index 00000000..d9929807 --- /dev/null +++ b/tests/adapters/every_adapter_mutable_sorter.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2018-2024 Morwenn + * SPDX-License-Identifier: MIT + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + //////////////////////////////////////////////////////////// + // Regular mutable sorter + + struct mutable_sorter_impl + { + int dummy1=0, dummy2=0; + + mutable_sorter_impl() = default; + constexpr mutable_sorter_impl(int a, int b): + dummy1(a), dummy2(b) + {} + + template< + typename Iterator, + typename Compare = std::less<>, + typename Projection = std::identity, + typename = std::enable_if_t< + cppsort::is_projection_iterator_v + > + > + auto operator()(Iterator first, Iterator last, + Compare compare={}, Projection projection={}) + -> void + { + dummy1 = 3; + cppsort::insertion_sort(std::move(first), std::move(last), + std::move(compare), std::move(projection)); + dummy2 = 11; + } + + using iterator_category = std::random_access_iterator_tag; + using is_always_stable = std::false_type; + }; + + struct mutable_sorter: + cppsort::sorter_facade + { + mutable_sorter() = default; + mutable_sorter(int a, int b): + cppsort::sorter_facade(a, b) + {} + }; +} + + +TEST_CASE( "test most adapters with a mutable sorter", + "[adapters][sorter_facade]" ) +{ + std::vector collection; + collection.reserve(65); + auto distribution = dist::shuffled{}; + distribution(std::back_inserter(collection), 65, 0); + + // Sorter that will be adapted by everything + auto original_sorter = mutable_sorter(5, 7); + + SECTION( "container_aware_adapter" ) + { + cppsort::container_aware_adapter adapted_sorter(original_sorter); + + adapted_sorter(collection, std::greater<>{}); + CHECK( std::is_sorted(collection.begin(), collection.end(), std::greater<>{}) ); + CHECK( adapted_sorter.get().dummy1 == 3 ); + CHECK( adapted_sorter.get().dummy2 == 11 ); + } + + SECTION( "hybrid_adapter" ) + { + cppsort::hybrid_adapter< + cppsort::merge_sorter, + mutable_sorter + > adapted_sorter(cppsort::merge_sort, original_sorter); + adapted_sorter(collection); + CHECK( std::is_sorted(std::begin(collection), std::end(collection)) ); + CHECK( adapted_sorter.template get<1>().dummy1 == 3 ); + CHECK( adapted_sorter.template get<1>().dummy2 == 11 ); + } + + SECTION( "indirect_adapter" ) + { + cppsort::indirect_adapter adapted_sorter(original_sorter); + + adapted_sorter(collection); + CHECK( std::is_sorted(std::begin(collection), std::end(collection)) ); + CHECK( adapted_sorter.get().dummy1 == 3 ); + CHECK( adapted_sorter.get().dummy2 == 11 ); + } + + SECTION( "out_of_place_adapter" ) + { + cppsort::out_of_place_adapter adapted_sorter(original_sorter); + + adapted_sorter(collection, std::greater<>{}); + CHECK( std::is_sorted(collection.begin(), collection.end(), std::greater<>{}) ); + CHECK( adapted_sorter.get().dummy1 == 3 ); + CHECK( adapted_sorter.get().dummy2 == 11 ); + } + + SECTION( "schwartz_adapter" ) + { + cppsort::schwartz_adapter adapted_sorter(original_sorter); + + adapted_sorter(collection); + CHECK( std::is_sorted(std::begin(collection), std::end(collection)) ); + CHECK( adapted_sorter.get().dummy1 == 3 ); + CHECK( adapted_sorter.get().dummy2 == 11 ); + } + + SECTION( "self_sort_adapter" ) + { + cppsort::self_sort_adapter adapted_sorter(original_sorter); + + std::list li; + distribution(std::back_inserter(li), 65, 0); + + adapted_sorter(li); + CHECK( std::is_sorted(std::begin(li), std::end(li)) ); + // List sorted itself without using the original sorter + CHECK( adapted_sorter.get().dummy1 == 5 ); + CHECK( adapted_sorter.get().dummy2 == 7 ); + + adapted_sorter(collection); + CHECK( std::is_sorted(std::begin(collection), std::end(collection)) ); + // Sorting a vector used the mutable sorter + CHECK( adapted_sorter.get().dummy1 == 3 ); + CHECK( adapted_sorter.get().dummy2 == 11 ); + } + + SECTION( "stable_adapter" ) + { + cppsort::stable_adapter adapted_sorter(original_sorter); + + adapted_sorter(collection); + CHECK( std::is_sorted(std::begin(collection), std::end(collection)) ); + CHECK( adapted_sorter.get().dummy1 == 3 ); + CHECK( adapted_sorter.get().dummy2 == 11 ); + } + + SECTION( "verge_adapter" ) + { + cppsort::verge_adapter adapted_sorter(original_sorter); + + adapted_sorter(collection); + CHECK( std::is_sorted(std::begin(collection), std::end(collection)) ); + CHECK( adapted_sorter.get().dummy1 == 3 ); + CHECK( adapted_sorter.get().dummy2 == 11 ); + } +} \ No newline at end of file diff --git a/tests/adapters/every_adapter_stateful_sorter.cpp b/tests/adapters/every_adapter_stateful_sorter.cpp index 05df1459..12be1f99 100644 --- a/tests/adapters/every_adapter_stateful_sorter.cpp +++ b/tests/adapters/every_adapter_stateful_sorter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2023 Morwenn + * Copyright (c) 2019-2024 Morwenn * SPDX-License-Identifier: MIT */ #include @@ -12,7 +12,6 @@ #include #include #include -#include #include #include