Jeremy

LanguageENZH

<algorithm>

class std::ranges::in_fun_result (C++20)

template< class I, class F >
struct in_fun_result;

// I - 	the type of the iterator that the ranges::in_fun_result stores.
// F - 	the type of the function object that the ranges::in_fun_result stores.

ranges::in_fun_result is a class template that provides a way to store an iterator and a function object as a single unit.

This class template has no base classes or declared members other than those shown below. Thus it is suitable for use with structured bindings.

  • Data members
Member name Definition
in a value (that is supposed to be an iterator) of type I.
fun a value (that is supposed to be a function object) of type F.
  • Member functions
// std::ranges::in_fun_result::operator in_fun_result<I2, F2>

template<class I2, class F2>
requires std::converible_to<const I&, I2> && std::convertible_to<const F&, F2>
constexpr operator in_fun_result<I2, F2>() const &;

template<class I2, class F2>
requires std::convertible_to<I, I2> && std::convertible_to<F, F2>
constexpr operator in_fun_result<I2, F2>() &&;

// Converts *this to the result by constructing every data member of the result from the corresponding member of *this.
// 1. Equivalent to return {in, fun};.
// 2. Equivalent to return {std::move(in), std::move(fun)};.
  • Standard library
Algorithm functions Definition
ranges::for_each (c++20) applies a unary function object to elements from a range
ranges::for_each_n (c++20) applies a function object to the first N elements of a sequence
  • Synopsis
namespace std::ranges
{
    template<class I, class F>
    struct in_fun_result
    {
        [[no_unique_address]] I in;
        [[no_unique_address]] F fun;

        template<class I2, class F2>
        requires std::convertible_to<const I&, I2> && std::convertible_to<const F&, F2>
        constexpr operator in_fun_result<I2, F2>() const &
        {
            return {in, fun};
        }

        template<class I2, class F2>
        requires std::convertible_to<I, I2> && std::convertible_to<F, F2>
        constexpr operator in_fun_result<I2, F2>() &&
        {
            return {std::move(in), std::move(fun)};
        }
    }
}
  • Notes

Each standard library algorithm that uses this family of return types declares a new alias type, e.g. using merge_result = in_in_out_result<I1, I2, O>;.

The names for such aliases are formed by adding the suffix “_result” to the algorithm’s name. So, the return type of std::ranges::merge can be named as std::ranges::merge_result.

Unlike std::pair and std::tuple, this class template has data members of meaningful names.

  • Example
#include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <ranges>

int main()
{
  int v[]{1, 2, 3};

  const std::ranges::in_fun_result res1 = std::ranges::for_each_n(
    v,
    std::size(v),
    [](int& x) {result x = -x;} // negating lambda
  );

  assert(res1.in == std::end(v));

  const std::ranges::in_fun_result res2 = std::ranges::for_each(
    std::begin(v),
    res1.in,
    [](int x) { std::cout << x << ' '; } // printing lambda
  )

  std::cout << "| ";

  std::ranges::for_each(v, res1.fun); // uses negating lambda
  std::ranges::for_each(v, res2.fun); // uses printing lambda
  std::cout << "\n";
}

std::ranges::in_in_result (C++20)

template< class I1, class I2 >
struct in_in_result;

ranges::in_in_result is a class template that provides a way to store two iterators as a single unit.

This class template has no base classes or declared members other than those shown below. Thus it is suitable for use with structured bindings.

All special member functions of this class template are implicitly declared, which makes specializations be aggregate classes, and propagate triviality, potentially-throwing-ness, and constexpr-ness of corresponding operations on data members.

  • Template parameters

    • I1, I2: the types of the iterators that the ranges::in_in_result stores.
  • Data members

Member name Definition
in1 a value (that supposed to be an iterator) of type I1.
in2 a value (that supposed to be an iterator) of type I2.

All these members are declared with attribute.

  • Member functions
std::ranges::in_in_result::operator in_in_resuly<II2, II2>

template<class II1, class II2>
requires std::convertible_to<const I1&, II1> && std::convertible_to<const I2&, II2>
constexpr operator in_in_result<II1, II2>() const &;

template<class II1, class II2>
requires std::convertible_to<I1, II1> && std::convertible_to<I2, II2>
constexpr operator in_in_result<II1, II2>() &&;
*

// Converts `*this` to the result by constructing every data memeber of the result from the corresponding member of `*this`.
// 1) Equivalent to return {in1, in2};.
// 2) Equivalent to return {std::move(in1), std::move(in2)};.
  • Standard libaray
Algorithm functions Definition
ranges::mismatch (C++20) finds the first position where two ranges differ
ranges::swap_ranges (C++20) swaps two ranges of elements
  • Synopsis
namespace std::ranges
{
    template<class I1, class I2>
    struct in_in_result
    {
        [[no_unique_address]] I1 in1;
        [[no_unique_address]] I2 in2;

        template<class II1, class II2>
        requires std::convertible_to<const I1&, II1> && std::convertible_to<const I2&, II2>
        constexpr operator in_in_result<II1, II2>() const &
        {
            return {in1, in2};
        }

        template<class II1, class II2>
        requires std::convertible_to<I1, II1> && std::convertible_to<I2, II2>
        constexpr operator in_in_result<II1, II2>() &&
        {
            return {std::move(in1), std::move(in2)};
        }
    };
}
  • Notes

Each standard library algorithm that uses this family of return types declares a new alias type, e.g. using merge_result = in_in_out_result<I1, I2, O>;.

The names for such aliases are formed by adding the suffix “_result” to the algorithm’s name. So, the return type of std::ranges::merge can be named as std::ranges::merge_result.

Unlike std::pair and std::tuple, this class template has data members of meaningful names.

  • Example
#include <algorithm>
#include <iostream>
#include <ranges>

int main()
{
  constexpr static auto in1 = {1, 2, 3, 4};
  constexpr static auto in2 = {1, 2, 4, 5};

  constexpr auto result {std::ranges::mismatch(in1, in2)};

  static_assert(2 == std::ranges::distance(in1.begin(), result.in1));
  static_assert(2 == std::ranges::distance(in2.begin(), result.in2));
}

std::ranges::in_out_result (C++20)

template< class I, class O >
struct in_out_result;

ranges::in_out_result is a class template that provides a way to store two iterators as a single unit.

This class template has no base classes or declared members other than those shown below. Thus it is suitable for use with structured bindings.

All special member functions of this class template are implicitly declared, which makes specializations be aggregate classes, and propagate triviality, potentially-throwing-ness, and constexpr-ness of corresponding operations on data members.

  • Template parameters

    • I, O : the types of the objects that the ranges::in_out_result stores.
  • Data members

Member name Definition
in a value (that is supposed to be an iterator) of type I.
out a value (that is supposed to be an iterator) of type O.
  • Member functions
template<class I2, class O2>
requires std::convertible_to<const I&, I2> && std::convertible_to<const O&, O2>
constexpr operator in_out_result<I2, O2>() const &;

template<class I2, class O2>
requires std::convertible_to<I, I2> && std::convertible_to<O, O2>
constexpr operator in_out_result<I2, O2>() &&;

/**
 * Converts *this to the result by constructing every data member of the result from the corresponding member of *this.
 *  1) Equivalent to return {in, out};.
    2) Equivalent to return {std::move(in), std::move(out)};.
 */
  • Standard library
Algorithm functions Definition
ranges::copy/ranges::copy_if (C++20) copies a range of elements to a new location
ranges::copy_n (C++20) copies a number of elements to a new location
ranges::copy_backward (C++20) copies a range of elements in backwards order
ranges::move (C++20) moves a range of elements to a new location
ranges::move_backward (C++20) moves a range of elements to a new location in backwards order
ranges::transform (C++20) applies a function to a range of elements
ranges::replace_copy/ranges::replace_copy_if (C++20) copies a range, replacing elements satisfying specific criteria with another value
ranges::remove_copy/ranges::remove_copy_if (C++20) copies a range of elements omitting those that satisfy specific criteria
ranges::unique_copy (C++20) creates a copy of some range of elements that contains no consecutive duplicates
ranges::reverse_copy (C++20) creates a copy of a range that is reversed
ranges::rotate_copy (C++20) copies and rotate a range of elements
ranges::partial_sort_copy (C++20) copies and partially sorts a range of elements
ranges::set_difference (C++20) computes the difference between two sets
ranges::uninitialized_copy (C++20) copies a range of objects to an uninitialized area of memory
ranges::uninitialized_copy_n (C++20) copies a number of objects to an uninitialized area of memory
ranges::uninitialized_move (C++20) moves a range of objects to an uninitialized area of memory
ranges::uninitialized_move_n (C++20) moves a number of objects to an uninitialized area of memory
  • Synopsis
namespace std::ranges
{
    template<class I, class O>
    struct in_out_result
    {
        [[no_unique_address]] I in;
        [[no_unique_address]] O out;

        template<class I2, class O2>
        requires std::convertible_to<const I&, I2> && std::convertible_to<const O&, O2>
        constexpr operator in_out_result<I2, O2>() const &
        {
            return {in, out};
        }

        template<class I2, class O2>
        requires std::convertible_to<I, I2> && std::convertible_to<O, O2>
        constexpr operator in_out_result<I2, O2>() &&
        {
            return {std::move(in), std::move(out)};
        }
    };
}
  • Example
#include <algorithm>
#include <array>
#include <cctype>
#include <iostream>
#include <ranges>

int main()
{
  constexpr char in[] = "transform" "\n";
  std::array<char, sizeof(in)> out;

  const auto result = std::ranges::transform(in, out.begin(), [](char c) { return std::toupper(c); });

  auto print = [](char c) { std::cout << c; };
  std::ranges::for_each(std::cbegin(in), result.in, print);
  std::ranges::for_each(out.cbegin(), result.out, print);
}

// Output:
// transform
// TRANSFORM

std::ranges::in_in_out_result

// Since C++20
template< class I1, class I2, class O >
struct in_in_out_result;

ranges::in_in_out_result is a class template that provides a way to store three iterators as a single unit.

This class template has no base classes or declared members other than those shown below. Thus it is suitable for use with structured bindings.

All special member functions of this class template are implicitly declared, which makes specializations be aggregate classes, and propagate triviality, potentially-throwing-ness, and constexpr-ness of corresponding operations on data members.

  • Template parameters

    • I1, I2, O: the types of the iterators that the ranges::in_in_out_result stores.
  • Data members

Member name Definition
in1 a value (that supported to be an iterator) of type I1.
in2 a value (that supported to be an iterator) of type I2.
out a value (that supported to be an iterator) of type O.
  • Member functions
template<class II1, class II2, class OO>
requires std::convertible_to<const I1&, II1> &&
         std::convertible_to<const I2&, II2> &&
         std::convertible_to<const O&, OO>
constexpr operator in_in_out_result<II1, II2, OO>() const &;


template<class II1, class II2, class OO>
requires std::convertible_to<I1, II1> &&
         std::convertible_to<I2, II2> &&
         std::convertible_to<O, OO>
constexpr operator in_in_out_result<II1, II2, OO>() &&;

/**
 * Converts *this to the result by constructing every data member of the result from the corresponding member of *this.
    1) Equivalent to return {in1, in2, out};.
    2) Equivalent to return {std::move(in1), std::move(in2), std::move(out)};.
 */
  • Algorithm functions
Function name Definition
ranges::transform (C++20) applies a function to a range of elements
ranges::merge (C++20) merges two sorted ranges
ranges::set_union (C++20) computes the union of two sets
ranges::set_intersection (C++20) computes the intersection of two sets
ranges::set_symmetric_difference (C++20) computes the symmetric difference between two sets
  • Synopsis
namespace std::ranges
{
    template<class I1, class I2, class O>
    struct in_in_out_result
    {
        [[no_unique_address]] I1 in1;
        [[no_unique_address]] I2 in2;
        [[no_unique_address]] O  out;

        template<class II1, class II2, class OO>
        requires std::convertible_to<const I1&, II1> &&
                 std::convertible_to<const I2&, II2> &&
                 std::convertible_to<const O&, OO>
        constexpr operator in_in_out_result<II1, II2, OO>() const &
        {
            return {in1, in2, out};
        }

        template<class II1, class II2, class OO>
        requires std::convertible_to<I1, II1> &&
                 std::convertible_to<I2, II2> &&
                 std::convertible_to<O, OO>
        constexpr operator in_in_out_result<II1, II2, OO>() &&
        {
            return {std::move(in1), std::move(in2), std::move(out)};
        }
    };
}
  • Notes

Each standard library algorithm that uses this family of return types declares a new alias type, e.g. using merge_result = in_in_out_result<I1, I2, O>;.

The names for such aliases are formed by adding the suffix “_result” to the algorithm’s name. So, the return type of std::ranges::merge can be named as std::ranges::merge_result.

Unlike std::pair and std::tuple, this class template has data members of meaningful names.

  • Example:
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <ranges>

void print(auto rem, auto first, auto last)
{
  for (std:: cout << rem << ": "; first != last; ++first)
    std::cout << *first << " ";
  std::cout << "\n";
}

int main()
{
  constexpr static auto in1 = {1, 2, 3, 4, 5, 5};
  constexpr static auto in2 = {3, 4, 5, 6, 7};
  std::array<int, std::size(in1) + std::size(in2) > our;

  const auto result = std::ranges::merge(in1, in2, out.begin());
  print("in1", in1.begin(), result.in1);
  print("in2", in2.begin(), result.in2);
  print("out", out.begin(), result.out);
}

/**
 * in1: 1 2 3 4 5 5
   in2: 3 4 5 6 7
   out: 1 2 3 3 4 4 5 5 5 6 7
 */

all_of, any_of, none_of (C++11)

// Since C++11
// Constexpr since C++20
template< class InputIt, class UnaryPred >
bool all_of( InputIt first, InputIt last, UnaryPred p );

// (since C++17)
template< class ExecutionPolicy, class ForwardIt, class UnaryPred >
bool all_of( ExecutionPolicy&& policy,
             ForwardIt first, ForwardIt last, UnaryPred p );

// Since C++11
// Constexpr since C++20
template< class InputIt, class UnaryPred >
bool any_of( InputIt first, InputIt last, UnaryPred p );

// (since C++17)
template< class ExecutionPolicy, class ForwardIt, class UnaryPred >
bool any_of( ExecutionPolicy&& policy,
             ForwardIt first, ForwardIt last, UnaryPred p );

// Since C++11
// Constexpr since C++20
template< class InputIt, class UnaryPred >
bool none_of( InputIt first, InputIt last, UnaryPred p );

// (since C++17)
template< class ExecutionPolicy, class ForwardIt, class UnaryPred >
bool none_of( ExecutionPolicy&& policy,
              ForwardIt first, ForwardIt last, UnaryPred p );

/**
 * 1) Checks if unary predicate p returns true for all elements in the range [first, last).
   3) Checks if unary predicate p returns true for at least one element in the range [first, last).
   5) Checks if unary predicate p returns true for none of the elements in the range [first, last).
   2,4,6) Same as (1,3,5), but executed according to policy.

    These overloads participate in overload resolution only if all following conditions are satisfied:
      std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> is true. (until C++20)
      std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> is true. (since C++20)
 */
  • Parameters

    • first, last: the pair of iterators defining the range of elements to examine
    • policy: the execution policy to use
    • p: unary predicate. The expression p(v) must be convertible to bool for every argument v of type (possibly const) VT, where VT is the value type of InputIt, regardless of value category, and must not modify v. Thus, a parameter type of VT&is not allowed, nor is VT unless for VT a move is equivalent to a copy(since C++11).​
  • Type requirements

    • InputIt must meet the requirements of LegacyInputIterator.
    • ForwardIt must meet the requirements of LegacyForwardIterator.
    • UnaryPred must meet the requirements of Predicate.
  • Complexity

    • 1-6) At most std::distance(first, last) applications of the predicate p.
  • Exceptions

The overloads with a template parameter named ExecutionPolicy report errors as follows:

- If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. For any other ExecutionPolicy, the behavior is implementation-defined.

- If the algorithm fails to allocate memory, std::bad_alloc is thrown.
  • Example
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>

int main() {
  std::vector<int> v(10, 2);
  std::partial_sum(v.cbegin(), v.cend(), v.begin());
  std::cout << "Amount the numbers: ";
  std::copy(v.cbegin(), v.cend(), std::ostream_iterator<int>(std::cout, " "));
  std::cout << "\n";

  if (std::all_of(v.cbegin(), v.cend(), [](int i) { return i % 2 == 0; }))
    std::cout << "All numbers are even\n";

  if (std::none_of(v.cbegin(), v.cend(),
                   std::bind(std::modulus<>(), std::placeholders::_1, 2)))
    std::cout << "None of them are odd\n";

  struct DivisibleBy {
    const int d;
    DivisibleBy(int n) : d(n) {}
    bool operator()(int n) const { return n % d == 0; }
  };

  if (std::any_of(v.cbegin(), v.cend(), DivisibleBy(7)))
    std::cout << "At least one number is divisible by 7\n";
}

/**
 * Amount the numbers: 2 4 6 8 10 12 14 16 18 20
   All numbers are even
   None of them are odd
   At least one number is divisible by 7
 */

std::for_each

// constexpr since C++20
template< class InputIt, class UnaryFunc >
UnaryFunc for_each( InputIt first, InputIt last, UnaryFunc f );

// since C++17
template< class ExecutionPolicy, class ForwardIt, class UnaryFunc >
void for_each( ExecutionPolicy&&, policy, ForwardIt first, ForwardIt last, UnaryFunc f);

Applies the given unary function object f to the result of dereferencing every iterator in the range [first, last). If f returns a result, the result is ignored.

  1. f is applied in order starting from first. If UnaryFunc is not MoveConstructible, the behavior is undefined. (since C++11)

  2. f might not be applied in order. The algorithm is executed according to policy. This overload participates in overload resolution only if all following conditions are satisfied: std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> is true. (until C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> is true. (since C++20)

If the iterator type (InputIt/ForwardIt) is mutable, f may modify the elements of the range through the dereferenced iterator.

Unlike the rest of the parallel algorithms, for_each is not allowed to make copies of the elements in the sequence even if they are TriviallyCopyable.

  • Parameters

    • first, last: the pair of iterators defining the range of elements to which the function object will be applied
    • policy: the execution policy to use
    • f: function object, to be applied to the result of dereferencing every iterator in the range [first, last)
  • Type requirements

    • InputIt must meet the requirements of LegacyInputIterator.
    • ForwardIt must meet the requirements of LegacyForwardIterator.
  • Return value

    • f
    • (none)
  • Complexity Exactly std::distance(first, last) applications of f.

  • Exceptions The overload with a template parameter named ExecutionPolicy reports errors as follows:

    • If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. For any other ExecutionPolicy, the behavior is implementation-defined.
    • If the algorithm fails to allocate memory, std::bad_alloc is thrown.
  • Possible implementation

template<class InputIt, class UnaryFunc>
constexpr UnaryFunc for_each(InputIt first, InputIt last, UnaryFunc f)
{
  for (; first != last; ++first)
    f(*first);

  return f;
}
  • Example
#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
  std::vector<int> v{3, -4, 2, -8, 15, 267};

  auto print = [](const int& n) { std::cout << n << ' '; };

  std::cout << "before:\t";
  std::for_each(v.cbegin(), v.cend(), print);
  std::cout << "\n";

  std::for_each(v.begin(), v.end(), [](int &n) {n++;});

  std::cout << "after:\t";
  std::for_each(v.cbegin(), v.cend(), print);
  std::cout << "\n";

  struct Sum
  {
    void operator()(int n) { sum += n; }
    int sum {0};
  };

  Sum s = std::for_each(v.cbegin(), v.cend(), Sum());
  std::cout << "sum:\t" << s.sum << "\n";
}

// Output
// before: 3 -4 2 -8 15 -267
// after 4 -3 3 -7 268
// sum: 281

std::for_each_n (C++17)

// since C++17
// constexpr since C++20
template< class InputIt, class Size, class UnaryFunc >
InputIt for_each_n( InputIt first, Size n, UnaryFunc f );

// since C++17
template< class ExecutionPolicy, class ForwardIt,
          class Size, class UnaryFunc >
ForwardIt for_each_n( ExecutionPolicy&& policy, ForwardIt first, Size n, UnaryFunc f );

Applies the given function object f to the result of dereferencing every iterator in the range [first, first + n). If f returns a result, the result is ignored.

  1. f is applied in order starting from first.
  1. f might not be applied in order. The algorithm is executed according to policy. This overload participates in overload resolution only if all following conditions are satisfied:

    std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> is true. (Until C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> is true. (since C++20)

    If UnaryFunc is not CopyConstructible, the behavior is undefined.

If n >= 0 is not true, the behavior is undefined.

If the iterator type (InputIt/ForwardIt) is mutable, f may modify the elements of the range through the dereferenced iterator.

Unlike the rest of the parallel algorithms, for_each_n is not allowed to make copies of the elements in the sequence even if they are TriviallyCopyable.

  • Parameters

    • first: the beginning of the range to apply the function to
    • n: the number of elements to apply the function to
    • policy: the execution policy to use
    • f: function object, to be applied to the result of dereferencing every iterator in the range [first, first + n) The signature of the function should be equivalent to the following: void fun(const Type &a); The type Type must be such that an object of type InputIt can be dereferenced and them implicitly converted to Type.
  • Type requirements

    • InputIt must meet the requirements of LegacyInputIterator.
    • ForwardIt must meet the requirements of LegacyForwardIterator.
    • Size must be convertible to an intergral type.
  • Return value

An iterator equal to first + n, or more formally, to std::advance(first, n).

  • Complexity

Exactly n applications of f;

  • Exceptions The overload with a template parameter named ExecutionPolicy reports errors as follows:

    • If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. For any other ExecutionPolicy, the behavior is implementation-defined.

    • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

  • Possible implementation

template<class InputIt, class Size, class UnaryFunc>
InputIt for_each_n(InputIt first, Size n, UnaryFunc f)
{
    for (Size i = 0; i < n; ++first, (void) ++i)
        f(*first);

    return first;
}
  • Example:
#include <algorithm>
#include <iostream>
#include <vector>

void println(auto const &v) {
  for (auto count{v.size()}; const auto &e : v)
    std::cout << e << (--count ? ", " : "\n");
}

int main() {
  std::vector<int> vi{1, 2, 3, 4, 5};
  println(vi);

  std::for_each_n(vi.begin(), 3, [](auto &n) { n *= 2; });
  println(vi);
}

/**
 * Output
 * 1, 2, 3, 4, 5
   2, 4, 6, 4, 5
 */