Skip to content

Commit

Permalink
Make stable_adapter<self_sort_adapter> work with mutable sorters (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
Morwenn committed Sep 8, 2024
1 parent 2bec62b commit d84e120
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 13 deletions.
28 changes: 15 additions & 13 deletions include/cpp-sort/detail/stable_adapter_self_sort_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,56 +45,58 @@ namespace cppsort

template<typename Collection, typename... Args>
requires 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_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()(first, 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()(first, last, std::forward<Args>(args)...))
{
return this->get()(first, last, std::forward<Args>(args)...);
return std::forward<Self>(self).get()(first, last, std::forward<Args>(args)...);
}

////////////////////////////////////////////////////////////
// Special cases for standard library lists whose sort
// method implements a stable sort

template<typename T>
auto operator()(std::forward_list<T>& collection) const
static auto operator()(std::forward_list<T>& collection)
-> void
{
collection.sort();
}

template<typename T, typename Compare>
requires (not is_projection_v<Compare, std::forward_list<T>&>)
auto operator()(std::forward_list<T>& collection, Compare compare) const
static auto operator()(std::forward_list<T>& collection, Compare compare)
-> void
{
collection.sort(utility::as_function(compare));
}

template<typename T>
auto operator()(std::list<T>& collection) const
static auto operator()(std::list<T>& collection)
-> void
{
collection.sort();
}

template<typename T, typename Compare>
requires (not is_projection_v<Compare, std::list<T>&>)
auto operator()(std::list<T>& collection, Compare compare) const
static auto operator()(std::list<T>& collection, Compare compare)
-> void
{
collection.sort(utility::as_function(compare));
Expand Down
21 changes: 21 additions & 0 deletions tests/adapters/every_adapter_mutable_sorter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,27 @@ TEST_CASE( "test most adapters with a mutable sorter",
CHECK( adapted_sorter.get().after_sort == mutable_state::modified );
}

SECTION( "stable_adapter<self_sorter_adapter>" )
{
cppsort::self_sort_adapter inner_adapter(original_sorter);
cppsort::stable_adapter adapted_sorter(inner_adapter);

std::list<int> li;
distribution(std::back_inserter(li), 65, 0);

adapted_sorter(li);
CHECK( std::is_sorted(li.begin(), li.end()) );
// List sorted itself without using the original sorter
CHECK( adapted_sorter.get().get().before_sort == mutable_state::initial );
CHECK( adapted_sorter.get().get().after_sort == mutable_state::initial );

adapted_sorter(collection);
CHECK( std::is_sorted(collection.begin(), collection.end()) );
// Sorting a vector used the mutable sorter
CHECK( adapted_sorter.get().get().before_sort == mutable_state::modified );
CHECK( adapted_sorter.get().get().after_sort == mutable_state::modified );
}

SECTION( "verge_adapter" )
{
cppsort::verge_adapter adapted_sorter(original_sorter);
Expand Down

0 comments on commit d84e120

Please sign in to comment.