Skip to content

Commit

Permalink
Remove cppsort::[stable_sort] (issue #167)
Browse files Browse the repository at this point in the history
  • Loading branch information
Morwenn committed Nov 1, 2020
1 parent d8724d3 commit 02c4fe6
Show file tree
Hide file tree
Showing 16 changed files with 86 additions and 760 deletions.
4 changes: 2 additions & 2 deletions docs/Library-nomenclature.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

* *Comparison function*: most of the sorting algorithms in the library are comparison sorts. It means that the algorithm uses a comparison function to know the order of the elements and sort them accordingly; such a comparison function shall take two values and have a return type convertible to `bool`. The available sorting algorithms transform comparison functions on the fly so that some pointers to member functions can also be used as comparison functions, as if called with [`std::invoke`](http://en.cppreference.com/w/cpp/utility/functional/invoke). The default comparison function used by the sorting algorithms is [`std::less<>`](http://en.cppreference.com/w/cpp/utility/functional/less_void). Many sorters can take a comparison function as an additional parameter. For example, using `std::greater<>` instead of the default comparison function would sort a collection in descending order.

cppsort::sort(collection, std::greater<>{});
cppsort::heap_sort(collection, std::greater<>{});

Some algorithms don't accept such an additional parameter. It may be because they implement a non-comparison sort instead, a sorting algorithm that uses other properties of the elements to perform the sort rather than a comparison function (for example a [radix sort](https://en.wikipedia.org/wiki/Radix_sort)).

Expand All @@ -30,7 +30,7 @@

struct wrapper { int value; };
std::vector<wrapper> collection = { /* ... */ };
cppsort::sort(collection, &wrapper::value);
cppsort::heap_sort(collection, &wrapper::value);

Every *comparison sorter* is also a *projection sorter*, but there are also projection-only sorters, such as [`spread_sorter`](https://github.com/Morwenn/cpp-sort/wiki/Sorters).

Expand Down
4 changes: 2 additions & 2 deletions docs/Sorters.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ While these function objects offer little more than regular sorting functions by
#include <cpp-sort/sorters.h>
```

Note that for every `foobar_sorter` described in this page, there is a corresponding `foobar_sort` global instance that allows not to care about the sorter abstraction as long as it is not needed (the instances are usable as regular function templates). The only sorter without a corresponding global instance is [`default_sorter`](https://github.com/Morwenn/cpp-sort/wiki/Sorters#default_sorter) since it mainly exists as a fallback sorter for the functions [`cppsort::sort` and `cppsort::stable_sort`](https://github.com/Morwenn/cpp-sort/wiki/Sorting-functions) when they are called without an explicit sorter.
Note that for every `foobar_sorter` described in this page, there is a corresponding `foobar_sort` global instance that allows not to care about the sorter abstraction as long as it is not needed (the instances are usable as regular function templates). The only sorter without a corresponding global instance is [`default_sorter`](https://github.com/Morwenn/cpp-sort/wiki/Sorters#default_sorter).

If you want to read more about sorters and/or write your own one, then you should have a look at [[the dedicated page|Writing a sorter]] or at [[a specific example|Writing a bubble_sorter]].

Expand Down Expand Up @@ -45,7 +45,7 @@ Whether this sorter works with types that are not default-constructible depends

***WARNING:** `default_sorter` is deprecated in version 1.8.0 and removed in version 2.0.0, see [issue #168](https://github.com/Morwenn/cpp-sort/issues/167) for the rationale.*

Sorter striving to use a sorting algorithm as optimized as possible. It is the fallback sorter used by [`cppsort::sort`](https://github.com/Morwenn/cpp-sort/wiki/sorting-function) when no sorter is given. The current implementation defines it as follows:
Sorter striving to use a sorting algorithm as optimized as possible. The current implementation defines it as follows:

```cpp
struct default_sorter:
Expand Down
167 changes: 0 additions & 167 deletions docs/Sorting-functions.md

This file was deleted.

2 changes: 1 addition & 1 deletion docs/Writing-a-bubble_sorter.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ struct bubble_sorter_impl
We can see several improvements compared to the previous version: first of all, we added an optional projection parameter which defauts to [`utility::identity`](https://github.com/Morwenn/cpp-sort/wiki/Miscellaneous-utilities#miscellaneous-function-objects). This is a function object that returns a value as is so that the default behaviour of the algorithm is to run *as if* projections didn't exist. It is very likely to be optimized aways by the compiler anyway.
The second modification is one I wish we could do without (yet another thing that concepts would make more expressive): [`is_projection_iterator_v`](https://github.com/Morwenn/cpp-sort/wiki/Sorter-traits#is_projection-and-is_projection_iterator) is a trait that checks whether a projection function can be used on a dereferenced iterator. It also optionally checks that a given comparison function can be called with the result of two such projections. This trait exists to ensure that `cppsort::sort` won't call the functor when these conditions are not satisfied, which may be crucial when aggregating sorters with [`hybrid_adapter`](https://github.com/Morwenn/cpp-sort/wiki/Sorter-adapters#hybrid_adapter).
The second modification is one I wish we could do without (yet another thing that concepts would make more expressive): [`is_projection_iterator_v`](https://github.com/Morwenn/cpp-sort/wiki/Sorter-traits#is_projection-and-is_projection_iterator) is a trait that checks whether a projection function can be used on a dereferenced iterator. It also optionally checks that a given comparison function can be called with the result of two such projections. This trait exists to ensure that a sorter's `operator()` won't be called when these conditions are not satisfied, which may be crucial when aggregating sorters with [`hybrid_adapter`](https://github.com/Morwenn/cpp-sort/wiki/Sorter-adapters#hybrid_adapter).
Now that you know how to handle projections in your algorithm, here is the interesting part: you generally don't need to manually handle projections. The class template `sorter_facade` generates overloads of `operator()` taking projection functions that bake the projection into the comparison and forward that mix to the sorter implementation. In our implementation of `bubble_sort`, we always use the projection inside the comparison, so handling the projections by hand isn't giving us any optimization opportunity; we might as well implement just the comparison and add the small required SFINAE check:
Expand Down
4 changes: 2 additions & 2 deletions docs/Writing-a-sorter.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ This kind of comparison sorters help to compare things that don't have an overlo
```cpp
// Sort collection in reverse order with std::sort
cppsort::sort(collection, std_sorter{}, std::greater<>{});
std_sorter{}(collection, std::greater<>{});
```

It is worth noting that every *comparison sorter* provided by the library transforms the comparison parameter with [`utility::as_function`](https://github.com/Morwenn/cpp-sort/wiki/Miscellaneous-utilities#as_function) before actually using it. It allows to use pointers to member functions of the `lhs.compare_to(rhs)` kind out-of-the-box.
Expand Down Expand Up @@ -207,7 +207,7 @@ Note that most of the algorithms (actually, every *projection sorter* provided b
```cpp
struct wrapper { int value; }
std::vector<wrapper> vec = { {5}, {9}, {6}, {1}, {2}, {8}, {3}, {0}, {7}, {4} };
cppsort::sort(vec, selection_sorter{}, &wrapper::value);
selection_sorter{}(vec, &wrapper::value);
```

Thanks to that small trick, the `selection_sorter` will sort `vec`, using the member data `wrapper::value` instead of a full `wrapper` instance (which cannot be compared) to perform the comparisons on.
Expand Down
1 change: 0 additions & 1 deletion docs/_Sidebar.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
* [[Home]]
* Sorting library
* [[Library nomenclature]]
* [[Sorting functions]]
* [[Sorters]]
* [[Fixed-size sorters]]
* [[Sorter adapters]]
Expand Down
2 changes: 1 addition & 1 deletion include/cpp-sort/adapters/container_aware_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace cppsort
{
namespace detail
{
// Hide the generic cppsort::sort
// Hide potential out-of-scope sort()
struct nope_type {};
template<typename... Args>
auto sort(Args&&...)
Expand Down
Loading

0 comments on commit 02c4fe6

Please sign in to comment.