std::ranges::is_sorted(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸŽ€ NAME πŸŽ€

std::ranges::is_sorted β€” std::ranges::is_sorted (yes bestie, that's the whole NAME section, and it's giving "the function is literally the function" πŸ’…). This is the std::ranges::is_sorted(3) page from the C++ Standard Libary manual, and we're about to make sortedness make sense. πŸ¦‹

✨ SYNOPSIS ✨

Defined in header <algorithm>

Call signature:

template< std::forward_iterator I, std::sentinel_for<I> S,
          class Proj = std::identity,
          std::indirect_strict_weak_order<std::projected<I, Proj>>
(1) (since C++20)
              Comp = ranges::less >
constexpr bool
    is_sorted( I first, S last, Comp comp = {}, Proj proj = {} );
template< ranges::forward_range R, class Proj = std::identity,
          std::indirect_strict_weak_order<
              std::projected<ranges::iterator_t<R>, Proj>>
(2) (since C++20)
              Comp = ranges::less >
constexpr bool
    is_sorted( R&& r, Comp comp = {}, Proj proj = {} );

Checks if the elements in range [first, last) are sorted in non-descending order. 🫢

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. No cap, that's the formal vibe. 😭

  1. Elements are compared using the given binary comparison function comp.
  2. Same as (1), but uses r as the source range, as if using ranges::begin(r) as first and ranges::end(r) as last.

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 check if it is sorted. πŸ‘€
  • r β€” the range to check if it is sorted.
  • comp β€” comparison function to apply to the projected elements.
  • proj β€” projection to apply to the elements.

🌈 RETURN VALUE 🌈

true if the elements in the range are sorted according to comp. Periodt. πŸ’–

⭐ COMPLEXITY ⭐

Linear in the distance between first and last. Slay, linear time. πŸ”₯

🧚 POSSIBLE IMPLEMENTATION 🧚

struct is_sorted_fn
{
    template<std::forward_iterator I, std::sentinel_for<I> S,
             class Proj = std::identity,
             std::indirect_strict_weak_order<std::projected<I, Proj>>
                 Comp = ranges::less>
    constexpr bool operator()(I first, S last, Comp comp = {}, Proj
proj = {}) const
    {
        return ranges::is_sorted_until(first, last, comp, proj) ==
last;
    }

    template<ranges::forward_range R, class Proj = std::identity,
             std::indirect_strict_weak_order<
                 std::projected<ranges::iterator_t<R>, Proj>>
                     Comp = ranges::less>
    constexpr bool operator()(R&& r, Comp comp = {}, Proj proj = {})
const
    {
        return (*this)(ranges::begin(r), ranges::end(r),
std::ref(comp), std::ref(proj));
    }
};

inline constexpr is_sorted_fn is_sorted;

πŸ“ NOTES πŸ“

ranges::is_sorted returns true for empty ranges and ranges of length one. Tiny ranges stay winning, bestie. πŸŽ€

πŸ“ EXAMPLE πŸ“

Here's the classic // Run this code demo:

#include <algorithm>
#include <array>
#include <functional>
#include <iostream>
#include <iterator>

int main()
{
    namespace ranges = std::ranges;

    std::array digits {3, 1, 4, 1, 5};

    ranges::copy(digits, std::ostream_iterator<int>(std::cout, " "));
    ranges::is_sorted(digits)
        ? std::cout << ": sorted\n"
        : std::cout << ": not sorted\n";

    ranges::sort(digits);

    ranges::copy(digits, std::ostream_iterator<int>(std::cout, " "));
    ranges::is_sorted(ranges::begin(digits), ranges::end(digits))
        ? std::cout << ": sorted\n"
        : std::cout << ": not sorted\n";

    ranges::reverse(digits);

    ranges::copy(digits, std::ostream_iterator<int>(std::cout, " "));
    ranges::is_sorted(digits, ranges::greater {})
        ? std::cout << ": sorted (with 'greater')\n"
        : std::cout << ": not sorted\n";
}

🌸 OUTPUT 🌸

3 1 4 1 5 : not sorted
1 1 3 4 5 : sorted
5 4 3 1 1 : sorted (with 'greater')

πŸ‘‘ SEE ALSO πŸ‘‘

  • ranges::is_sorted_until β€” finds the largest sorted subrange (C++20) (niebloid)
  • is_sorted β€” checks whether a range is sorted into ascending order (C++11) (function template)

Source check, bestie: http://cppreference.com, version 2024.06.10, page std::ranges::is_sorted(3) β€” mwah πŸ’‹βœ¨

πŸ“¦ where this page comes from