std::ranges::in_fun_result(3)

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

🌸 std::ranges::in_fun_result β€” C++ Standard Libary 🌸

okay so bestie, welcome to the std::ranges::in_fun_result(3) page from the C++ Standard Libary β€” yes, that's the manual name, and we're keeping it exactly like that. This whole page is about a class template that bundles an iterator and a function object into one cute lil unit. Structured-binding-friendly, no cap. πŸ’…


πŸ“› NAME

std::ranges::in_fun_result β€” std::ranges::in_fun_result


✨ Synopsis

Defined in header <algorithm>
template< class I, class F >   (since C++20)
struct in_fun_result;

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

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

technical tea β˜•: 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. that's a mouthful but it's literally important.

🧚 Template parameters

  • 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. πŸ¦‹

πŸŽ€ Data members

  • in β€” a value (that is supposed to be an iterator) of type I. (public member object) πŸ’–
  • fun β€” a value (that is supposed to be a function object) of type F. (public member object) πŸ’–

All these members are declared with the [[no_unique_address]] attribute. slay. 🌸


πŸ’… Member functions

πŸŒ€ std::ranges::in_fun_result::operator in_fun_result<I2, F2>

  1. first overload β€” const &:
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 &;
  1. second overload β€” &&:
template<class I2, class F2>
requires std::convertible_to<I, I2> && std::convertible_to<F, F2>
constexpr operator in_fun_result<I2, F2>() &&;

This converts *this to the result by constructing every data member of the result from the corresponding member of *this. clean, cute, no chaos. πŸŽ€

  1. Equivalent to return {in, fun};.
  2. Equivalent to return {std::move(in), std::move(fun)};.

🌈 Standard library

The following standard library functions use ranges::in_fun_result as the return type:

🌟 Algorithm functions

  • ranges::for_each (C++20) β€” applies a function to a range of elements (niebloid) πŸ”₯
  • ranges::for_each_n (C++20) β€” applies a function object to the first N elements of a sequence (niebloid) πŸ”₯

πŸ”₯ 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 way that works is that 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. periodt. πŸ’…


πŸ¦‹ Example

// Run this code

#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) { return 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';
}

πŸ“ Output

-1 -2 -3 β”‚ 1 2 3

🌸 See also

  • pair β€” implements binary tuple, i.e. a pair of values (class template) πŸŽ€
  • tuple (C++11) β€” implements fixed size container, which holds elements of possibly different types (class template) πŸŽ€

okay bestie, that's the whole page. source/version/date vibes: http://cppreference.com Β· 2024.06.10 Β· std::ranges::in_fun_result(3). now go forth and use structured bindings responsibly πŸ’…βœ¨

πŸ“¦ where this page comes from