Skip to content

Commit

Permalink
Make most adapters work with mutable sorters (issue #104)
Browse files Browse the repository at this point in the history
  • Loading branch information
Morwenn committed Aug 5, 2024
1 parent c3fdc72 commit ae67ba2
Show file tree
Hide file tree
Showing 12 changed files with 448 additions and 146 deletions.
218 changes: 156 additions & 62 deletions include/cpp-sort/adapters/container_aware_adapter.h

Large diffs are not rendered by default.

25 changes: 14 additions & 11 deletions include/cpp-sort/adapters/hybrid_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ namespace cppsort
struct hybrid_adapter_storage_leaf:
utility::adapter_storage<Sorter>
{
using base_class = utility::adapter_storage<Sorter>;

hybrid_adapter_storage_leaf() = default;

constexpr hybrid_adapter_storage_leaf(Sorter&& sorter):
Expand All @@ -91,11 +93,11 @@ namespace cppsort
// preferred for its iterator category first, then for its
// position into the sorters

template<typename... Args>
constexpr auto operator()(choice<Ind>, Args&&... args) const
-> decltype(this->get()(std::forward<Args>(args)...))
template<typename Self, typename... Args>
constexpr auto operator()(this Self&& self, choice<Ind>, Args&&... args)
-> decltype(std::forward<Self>(self).base_class::get()(std::forward<Args>(args)...))
{
return this->get()(std::forward<Args>(args)...);
return std::forward<Self>(self).base_class::get()(std::forward<Args>(args)...);
}

template<typename... Args>
Expand Down Expand Up @@ -209,34 +211,35 @@ namespace cppsort
////////////////////////////////////////////////////////////
// Call operator

template<mstd::forward_range Range, typename... Args>
constexpr auto operator()(Range&& range, Args&&... args) const
-> decltype(base_class::operator()(
template<typename Self, mstd::forward_range Range, typename... Args>
constexpr auto operator()(this Self&& self, Range&& range, Args&&... args)
-> decltype(std::forward<Self>(self).base_class::operator()(
detail::choice_for_it<mstd::iterator_t<Range>, sizeof...(Sorters)>{},
std::forward<Range>(range),
std::forward<Args>(args)...
))
{
return base_class::operator()(
return std::forward<Self>(self).base_class::operator()(
detail::choice_for_it<mstd::iterator_t<Range>, sizeof...(Sorters)>{},
std::forward<Range>(range),
std::forward<Args>(args)...
);
}

template<
typename Self,
mstd::forward_iterator Iterator,
mstd::sentinel_for<Iterator> 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>(self).base_class::operator()(
detail::choice_for_it<Iterator, sizeof...(Sorters)>{},
std::move(first), std::move(last),
std::forward<Args>(args)...
))
{
return base_class::operator()(
return std::forward<Self>(self).base_class::operator()(
detail::choice_for_it<Iterator, sizeof...(Sorters)>{},
std::move(first), std::move(last),
std::forward<Args>(args)...
Expand Down
20 changes: 13 additions & 7 deletions include/cpp-sort/adapters/indirect_adapter.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2022 Morwenn
* Copyright (c) 2015-2024 Morwenn
* SPDX-License-Identifier: MIT
*/
#ifndef CPPSORT_ADAPTERS_INDIRECT_ADAPTER_H_
Expand Down Expand Up @@ -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<Projection, Range, Compare>
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>(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>(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<Iterator> Sentinel,
typename Compare = std::less<>,
typename Projection = std::identity
>
requires is_projection_iterator_v<Projection, Iterator, Compare>
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>(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>(self).get(),
first, mstd::next(first, last),
mstd::distance(first, last),
std::move(compare), std::move(projection));
}
Expand Down
20 changes: 12 additions & 8 deletions include/cpp-sort/adapters/out_of_place_adapter.h
Original file line number Diff line number Diff line change
@@ -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_
Expand Down Expand Up @@ -31,7 +31,7 @@ namespace cppsort
{
template<typename Sorter, typename ForwardIterator, typename Size, typename... Args>
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<ForwardIterator>;
Expand All @@ -47,7 +47,8 @@ namespace cppsort
});

// Sort the elements in the memory buffer
return sorter(buffer.begin(), buffer.end(), std::forward<Args>(args)...);
return std::forward<Sorter>(sorter)(buffer.begin(), buffer.end(),
std::forward<Args>(args)...);
}
}

Expand All @@ -73,26 +74,29 @@ namespace cppsort
// Wrap and call the sorter

template<
typename Self,
mstd::forward_iterator Iterator,
mstd::sentinel_for<Iterator> 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>(args)...);
std::forward<Self>(self).get(),
std::forward<Args>(args)...);
}

template<mstd::forward_range Range, typename... Args>
auto operator()(Range&& range, Args&&... args) const
template<typename Self, mstd::forward_range Range, typename... Args>
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>(args)...);
std::forward<Self>(self).get(),
std::forward<Args>(args)...);
}

////////////////////////////////////////////////////////////
Expand Down
53 changes: 34 additions & 19 deletions include/cpp-sort/adapters/schwartz_adapter.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2022 Morwenn
* Copyright (c) 2016-2024 Morwenn
* SPDX-License-Identifier: MIT
*/
#ifndef CPPSORT_ADAPTERS_SCHWARTZ_ADAPTER_H_
Expand Down Expand Up @@ -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<Projection, Range, Compare>
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>(self).get());
}

template<
typename Self,
mstd::forward_iterator Iterator,
mstd::sentinel_for<Iterator> Sentinel,
typename Compare = std::less<>,
typename Projection = std::identity
>
requires is_projection_iterator_v<Projection, Iterator, Compare>
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>(self).get());
}

template<
typename Self,
mstd::forward_range Range,
typename Compare = std::less<>
>
requires (not is_projection_v<Compare, Range>)
auto operator()(Range&& range, Compare compare={}) const
-> decltype(this->get()(std::forward<Range>(range), std::move(compare)))
auto operator()(this Self&& self, Range&& range, Compare compare={})
-> decltype(std::forward<Self>(self).get()(
std::forward<Range>(range), std::move(compare)))
{
// No projection to handle, forward everything to the adapted sorter
return this->get()(std::forward<Range>(range), std::move(compare));
return std::forward<Self>(self).get()(
std::forward<Range>(range), std::move(compare));
}

template<
typename Self,
mstd::forward_iterator Iterator,
mstd::sentinel_for<Iterator> Sentinel,
typename Compare = std::less<>
>
requires (not is_projection_iterator_v<Compare, Iterator>)
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>(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>(self).get()(
std::move(first), std::move(last), std::move(compare));
}

template<mstd::forward_range Range, typename Compare>
auto operator()(Range&& range, Compare compare, std::identity projection) const
-> decltype(this->get()(std::forward<Range>(range), std::move(compare), projection))
template<typename Self, mstd::forward_range Range, typename Compare>
auto operator()(this Self&& self, Range&& range,
Compare compare, std::identity projection)
-> decltype(std::forward<Self>(self).get()(
std::forward<Range>(range), std::move(compare), projection))
{
// std::identity does nothing, bypass schartz_adapter entirely
return this->get()(std::forward<Range>(range), std::move(compare), projection);
return std::forward<Self>(self).get()(
std::forward<Range>(range), std::move(compare), projection);
}

template<
typename Self,
mstd::forward_iterator Iterator,
mstd::sentinel_for<Iterator> 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>(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>(self).get()(
std::move(first), std::move(last), std::move(compare), projection);
}
};
}
Expand Down
36 changes: 19 additions & 17 deletions include/cpp-sort/adapters/self_sort_adapter.h
Original file line number Diff line number Diff line change
@@ -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_
Expand Down Expand Up @@ -28,14 +28,14 @@ namespace cppsort

template<typename Collection, typename... Args>
concept has_sort_method =
requires (Collection& collection, Args&&... args) {
collection.sort(std::forward<Args>(args)...);
requires (Collection&& collection, Args&&... args) {
std::forward<Collection>(collection).sort(std::forward<Args>(args)...);
};

template<typename Collection, typename... Args>
concept has_stable_sort_method =
requires (Collection& collection, Args&&... args) {
collection.stable_sort(std::forward<Args>(args)...);
requires (Collection&& collection, Args&&... args) {
std::forward<Collection>(collection).stable_sort(std::forward<Args>(args)...);
};
}

Expand Down Expand Up @@ -65,7 +65,7 @@ namespace cppsort

template<typename Collection, typename... Args>
requires detail::has_sort_method<Collection, Args...>
auto operator()(Collection&& collection, Args&&... args) const
static auto operator()(Collection&& collection, Args&&... args)
-> decltype(std::forward<Collection>(collection).sort(utility::as_function(args)...))
{
return std::forward<Collection>(collection).sort(utility::as_function(args)...);
Expand All @@ -76,30 +76,32 @@ namespace cppsort
not detail::has_sort_method<Collection, Args...> &&
detail::has_stable_sort_method<Collection, Args...>
)
auto operator()(Collection&& collection, Args&&... args) const
static auto operator()(Collection&& collection, Args&&... args)
-> decltype(std::forward<Collection>(collection).stable_sort(utility::as_function(args)...))
{
return std::forward<Collection>(collection).stable_sort(utility::as_function(args)...);
}

template<typename Collection, typename... Args>
template<typename Self, typename Collection, typename... Args>
requires (
not detail::has_sort_method<Collection, Args...> &&
not detail::has_stable_sort_method<Collection, Args...>
)
auto operator()(Collection&& collection, Args&&... args) const
-> decltype(this->get()(std::forward<Collection>(collection), std::forward<Args>(args)...))
auto operator()(this Self&& self, Collection&& collection, Args&&... args)
-> decltype(std::forward<Self>(self).get()(
std::forward<Collection>(collection), std::forward<Args>(args)...))
{
return this->get()(std::forward<Collection>(collection), std::forward<Args>(args)...);
return std::forward<Self>(self).get()(
std::forward<Collection>(collection), std::forward<Args>(args)...);
}

template<typename Iterator, typename... Args>
auto operator()(Iterator first, Iterator last, Args&&... args) const
-> decltype(this->get()(std::move(first), std::move(last),
std::forward<Args>(args)...))
template<typename Self, typename Iterator, typename... Args>
auto operator()(this Self&& self, Iterator first, Iterator last, Args&&... args)
-> decltype(std::forward<Self>(self).get()(
std::move(first), std::move(last), std::forward<Args>(args)...))
{
return this->get()(std::move(first), std::move(last),
std::forward<Args>(args)...);
return std::forward<Self>(self).get()(
std::move(first), std::move(last), std::forward<Args>(args)...);
}

////////////////////////////////////////////////////////////
Expand Down
Loading

0 comments on commit ae67ba2

Please sign in to comment.