std::ranges::sort(3)
๐ std::ranges::sort ๐
okay bestie, you're on the std::ranges::sort(3) page from the C++ Standard Libary manual, and yes it's literally the std::ranges::sort algorithm in all its C++20 glory. ๐ This is the whole thing โ every signature, parameter, code block, output line, note, and SEE ALSO reference is coming with us. No cap, nothing skipped. ๐
๐ NAME ๐
std::ranges::sortโstd::ranges::sort. That's the name. Iconic, honestly. ๐
โจ Synopsis โจ
Defined in header <algorithm>.
๐ Call signature ๐
template< std::random_access_iterator I, std::sentinel_for<I> S,
class Comp = ranges::less, class Proj = std::identity >
requires std::sortable<I, Comp, Proj>
(1) (since C++20)
constexpr I
sort( I first, S last, Comp comp = {}, Proj proj = {} );
template< ranges::random_access_range R, class Comp =
ranges::less,
class Proj = std::identity >
(2) (since C++20)
requires std::sortable<ranges::iterator_t<R>, Comp, Proj>
constexpr ranges::borrowed_iterator_t<R>
sort( R&& r, Comp comp = {}, Proj proj = {} );
So what does it do? It sorts the elements in the range [first, last) in non-descending order. The order of equivalent elements is not guaranteed to be preserved. That's the tea. ๐ซ
A sequence is sorted with respect to a comparator comp if for any iterator it pointing to the sequence and any non-negative integer n such that it + n is a valid iterator pointing to an element of the sequence, std::invoke(comp, std::invoke(proj, *(it + n)), std::invoke(proj, *it)) evaluates to false. Yes, that's the official vibe check. ๐
- Elements are compared using the given binary comparison function
comp. - Same as (1), but uses
ras the source range, as if usingranges::begin(r)asfirstandranges::end(r)aslast.
The function-like entities described on this page are niebloids, that is:
- Explicit template argument lists cannot be specified when calling any of them.
- None of them are visible to argument-dependent lookup.
- When any of them are found by normal unqualified lookup as the name to the left of the function-call operator, argument-dependent lookup is inhibited.
In practice, they may be implemented as function objects, or with special compiler extensions. โจ
๐ธ Parameters ๐ธ
first,lastโ iterator-sentinel defining the range to sort.rโ the range to sort.compโ comparison to apply to the projected elements.projโ projection to apply to the elements.
๐ฆ Return value ๐ฆ
An iterator equal to last. That's it. Slay. ๐
๐ฅ Complexity ๐ฅ
\(\scriptsize \mathcal{O}(N\cdot\log{(N)})\)๐(Nยทlog(N)) comparisons and projections, where N = ranges::distance(first, last). Math girlies rise. ๐งฎโจ
๐ Possible implementation ๐
Note that typical implementations use Introsort. See also the implementation in MSVC STL and libstdc++.
Here's the implementation exactly as the page gives it โ no edits, just handing it over:
struct sort_fn {
template<std::random_access_iterator I, std::sentinel_for<I> S,
class Comp = ranges::less, class Proj = std::identity>
requires std::sortable<I, Comp, Proj>
constexpr I
operator()(I first, S last, Comp comp = {}, Proj proj = {})
const
{
if (first == last)
return first;
I last_iter = ranges::next(first, last);
ranges::make_heap(first, last_iter, std::ref(comp),
std::ref(proj));
ranges::sort_heap(first, last_iter, std::ref(comp),
std::ref(proj));
return last_iter;
}
template<ranges::random_access_range R, class Comp = ranges::less,
class Proj = std::identity>
requires std::sortable<ranges::iterator_t<R>, Comp, Proj>
constexpr ranges::borrowed_iterator_t<R>
operator()(R&& r, Comp comp = {}, Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r),
std::move(comp), std::move(proj));
} };
inline constexpr sort_fn sort {};
๐ Notes ๐
std::sort uses std::iter_swap to swap elements, whereas ranges::sort instead uses ranges::iter_swap (which performs ADL for iter_swap, unlike std::iter_swap). Little swap lore for you. ๐ซถ
๐ Example ๐
// Run this code
#include <algorithm>
#include <array>
#include <functional>
#include <iomanip>
#include <iostream>
void print(auto comment, auto const& seq, char term = ' ')
{
for (std::cout << comment << '\n'; auto const& elem : seq)
std::cout << elem << term;
std::cout << '\n';
}
struct Particle
{
std::string name; double mass; // MeV
template<class Os> friend
Os& operator<<(Os& os, Particle const& p)
{
return os << std::left << std::setw(8) << p.name << " : " <<
p.mass << ' ';
}
};
int main()
{
std::array s {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
namespace ranges = std::ranges;
ranges::sort(s);
print("Sort using the default operator<", s);
ranges::sort(s, ranges::greater());
print("Sort using a standard library compare function object", s);
struct
{
bool operator()(int a, int b) const { return a < b; }
} customLess;
ranges::sort(s.begin(), s.end(), customLess);
print("Sort using a custom function object", s);
ranges::sort(s, [](int a, int b) { return a > b; });
print("Sort using a lambda expression", s);
Particle particles[]
{
{"Electron", 0.511}, {"Muon", 105.66}, {"Tau", 1776.86},
{"Positron", 0.511}, {"Proton", 938.27}, {"Neutron", 939.57}
};
ranges::sort(particles, {}, &Particle::name);
print("\nSort by name using a projection", particles, '\n');
ranges::sort(particles, {}, &Particle::mass);
print("Sort by mass using a projection", particles, '\n');
}
๐จ๏ธ Output ๐จ๏ธ
Sort using the default operator<
0 1 2 3 4 5 6 7 8 9
Sort using a standard library compare function object
9 8 7 6 5 4 3 2 1 0
Sort using a custom function object
0 1 2 3 4 5 6 7 8 9
Sort using a lambda expression
9 8 7 6 5 4 3 2 1 0
Sort by name using a projection
Electron : 0.511
Muon : 105.66
Neutron : 939.57
Positron : 0.511
Proton : 938.27
Tau : 1776.86
Sort by mass using a projection
Electron : 0.511
Positron : 0.511
Muon : 105.66
Proton : 938.27
Neutron : 939.57
Tau : 1776.86
๐ See also ๐
ranges::partial_sortโ sorts the firstNelements of a range(C++20)(niebloid).ranges::stable_sortโ sorts a range of elements while preserving order between equal elements(C++20)(niebloid).ranges::partitionโ divides a range of elements into two groups(C++20)(niebloid).sortโ sorts a range into ascending order(function template).
that's the page, bestie! ๐
source: http://cppreference.com โข version/date: 2024.06.10 โข page: std::ranges::sort(3) โจ
๐ฆ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 ยท MIT
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms