std::ranges::sort în C++

Sortează un container întreg dintr-un apel, cu opțiunea de a sorta după un câmp (proiecție).

Sintaxă
std::ranges::sort(R&& r, Comp comp = {}, Proj proj = {});
std::ranges::sort(It first, Sent last, Comp comp = {}, Proj proj = {});

Ce face std::ranges::sort

Algoritmii din std::ranges (C++20) primesc direct containerul: std::ranges::sort(v) în loc de std::sort(v.begin(), v.end()). Sunt și mai stricți: dacă tipul nu se poate sorta, eroarea de compilare este mai clară.

Noutatea importantă este proiecția, al treilea argument: o funcție sau un pointer la membru care spune după ce se compară. std::ranges::sort(elevi, {}, &Elev::medie) sortează după medie fără să scrii o lambda de comparare. Al doilea argument, {}, înseamnă comparatorul implicit (std::ranges::less).

Aproape toți algoritmii din <algorithm> au o variantă în std::ranges: find, count_if, max_element, copy etc.

Parametri

Parametru Descriere
r Containerul (sau orice range cu acces direct).
comp Opțional. Comparatorul; {} înseamnă crescător, std::ranges::greater{} descrescător.
proj Opțional. Proiecția: după ce valoare se compară fiecare element.

Ce returnează

Un iterator către sfârșitul range-ului (de obicei ignorat).

Exemple

Exemplul 1: Clasic și ranges, unul lângă altul

#include <algorithm>
#include <functional>
#include <print>
#include <vector>

int main() {
    std::vector<int> a{5, 2, 8, 1};
    std::vector<int> b = a;

    std::sort(a.begin(), a.end());  // stil clasic
    std::ranges::sort(b);           // C++20

    std::println("{} {}", a, b);

    std::ranges::sort(b, std::ranges::greater{});
    std::println("Descrescător: {}", b);
}

Rezultat

[1, 2, 5, 8] [1, 2, 5, 8]
Descrescător: [8, 5, 2, 1]

Exemplul 2: Sortare după câmp, cu proiecție

#include <algorithm>
#include <functional>
#include <print>
#include <string>
#include <vector>

struct Oras {
    std::string nume;
    int locuitori;
};

int main() {
    std::vector<Oras> orase{{"Iași", 271692}, {"Cluj-Napoca", 286598}, {"Timișoara", 250849}, {"Constanța", 263688}};

    std::ranges::sort(orase, std::ranges::greater{}, &Oras::locuitori);
    for (const Oras& o : orase) {
        std::println("{:<12} {:>7}", o.nume, o.locuitori);
    }

    std::ranges::sort(orase, {}, &Oras::nume);
    std::println("Primul alfabetic: {}", orase.front().nume);
}

Rezultat

Cluj-Napoca   286598
Iași          271692
Constanța     263688
Timișoara     250849
Primul alfabetic: Cluj-Napoca

Exemplul 3: Proiecție cu lambda: sortare după lungime

#include <algorithm>
#include <print>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> parole{"soare123", "a1", "Parola!Lunga2026", "qwerty"};

    std::ranges::sort(parole, {}, [](const std::string& p) { return p.size(); });
    std::println("{}", parole);
}

Rezultat

["a1", "qwerty", "soare123", "Parola!Lunga2026"]

Greșeli frecvente

  • Scrii std::ranges::sort(v, &Oras::nume), fără {}: pointerul la membru este luat drept comparator și codul nu compilează. Proiecția este al treilea argument.
  • Încerci std::ranges::sort pe un std::list sau pe un view filtrat: nu compilează, pentru că trebuie acces direct la elemente.

Comenzi înrudite

  • std::sort: Sortează elementele dintr-un interval, crescător sau după o regulă dată de tine.
  • std::stable_sort: Sortează un interval păstrând ordinea inițială a elementelor considerate egale.
  • std::ranges::find: Caută o valoare direct într-un container, opțional după un câmp al elementelor (proiecție).
  • std::ranges::to: Transformă un range sau un view (filtrat, transformat) într-un container nou: vector, set, string, map.