std::ranges...:common_view(3)

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

✨ std::ranges::views::common, std::ranges::common_view ✨

okay bestie, this is straight from the C++ Standard Libary manual (yes, that spelling is in the header and we're keeping it πŸ’…), page std::ranges...:common_view(3). it's giving range-adaptor realness, and we're gonna keep every single deet. let's go 🫢


πŸ’– NAME πŸ’–

  • std::ranges::views::common,std::ranges::common_view β€” the name, periodt.
  • std::ranges::views::common,std::ranges::common_view β€” and here it is again, because the original NAME section lists it twice and we are not erasing details, no cap.

✨ Synopsis ✨

          Defined in header <ranges>
          template< ranges::view V >

              requires (not ranges::common_range<V> and
                        std::copyable<ranges::iterator_t<V>>)
       (1) (since C++20)
          class common_view

              : public ranges::view_interface<common_view<V>>
          namespace views {

              inline constexpr /* unspecified */ common = /* unspecified */;
       (2) (since C++20)

          }
          Call signature
          template< ranges::viewable_range R >

              requires /* see below */
       (since C++20)

          constexpr ranges::view auto common( R&& r );
  1. Adapts a given view with different types for iterator/sentinel pair into a view that is also a common_range. A common_view always has the same iterator/sentinel type.
  2. RangeAdaptorObject. Let e be a subexpression. Then the expression views::common(e) is expression-equivalent to:
    • views::all(e), if it is a well-formed expression and decltype((e)) models common_range;
    • common_view{e} otherwise.

🫢 Member functions 🫢

  • constructor β€” constructs a common_view (C++20) (public member function)
  • base β€” returns a copy of the underlying (adapted) view (C++20) (public member function)
  • begin β€” returns an iterator to the beginning (C++20) (public member function)
  • end β€” returns an iterator to the end (C++20) (public member function)
  • size β€” returns the number of elements. Provided only if the underlying (adapted) range satisfies sized_range. (C++20) (public member function)

🌸 Inherited from std::ranges::view_interface 🌸

  • empty β€” returns whether the derived view is empty. Provided if it satisfies sized_range or forward_range. (C++20) (public member function of std::ranges::view_interface<D>)
  • cbegin β€” returns a constant iterator to the beginning of the range. (C++23) (public member function of std::ranges::view_interface<D>)
  • cend β€” returns a sentinel for the constant iterator of the range. (C++23) (public member function of std::ranges::view_interface<D>)
  • operator bool β€” returns whether the derived view is not empty. Provided if ranges::empty is applicable to it. (C++20) (public member function of std::ranges::view_interface<D>)
  • data β€” gets the address of derived view's data. Provided if its iterator type satisfies contiguous_iterator. (C++20) (public member function of std::ranges::view_interface<D>)
  • front β€” returns the first element in the derived view. Provided if it satisfies forward_range. (C++20) (public member function of std::ranges::view_interface<D>)
  • back β€” returns the last element in the derived view. Provided if it satisfies bidirectional_range and common_range. (C++20) (public member function of std::ranges::view_interface<D>)
  • operator[] β€” returns the n^th element in the derived view. Provided if it satisfies random_access_range. (C++20) (public member function of std::ranges::view_interface<D>)

πŸŽ€ Deduction guides πŸŽ€

the original page has this heading and then... literally nothing else under it. so we're keeping it cute and empty: πŸ’…

🧚 Helper templates 🧚

          template< class T >

          inline constexpr bool
       (since C++20)
          enable_borrowed_range<std::ranges::common_view<T>> =

              std::ranges::enable_borrowed_range<T>;

This specialization of std::ranges::enable_borrowed_range makes common_view satisfy borrowed_range when the underlying view satisfies it.

πŸ’… Notes πŸ’…

common_view can be useful for working with legacy algorithms that expect the iterator and sentinel are of the same type. iykyk, bestie β€” legacy algorithms stay wanting matching types 🫠

πŸ”₯ Example πŸ”₯

// Run this code β€” yes, that's in the original, so here's the code:

        #include <iostream>
        #include <iterator>
        #include <list>
        #include <numeric>
        #include <ranges>

        int main()
        {
            auto v1 = {1, 2, 3, 4, 5};
            auto i1 = std::counted_iterator{v1.begin(), std::ssize(v1)};
            auto r1 = std::ranges::subrange{i1, std::default_sentinel};
        //  auto e1 = std::accumulate(r1.begin(), r1.end(), 0); // error:
       "common range" required
            auto c1 = std::ranges::common_view{r1};
            std::cout << "accumulate: " << std::accumulate(c1.begin(),
       c1.end(), 0) << '\n';

            // inherited from ranges::view_interface:
            std::cout << "c1.front(): " << c1.front() << '\n';
            std::cout << "c1.back(): " << c1.back() << '\n';
            std::cout << "c1.data(): " << c1.data() << '\n';
            std::cout << "c1[0]: " << c1[0] << '\n';

            auto v2 = std::list{1, 2, 3, 4, 5};
            auto i2 = std::counted_iterator{v2.begin(), std::ssize(v2)};
            auto r2 = std::ranges::subrange{i2, std::default_sentinel};
        //  auto e2 = std::accumulate(r2.begin(), r2.end(), 0); // error:
       "common range" required
            auto c2 = std::ranges::common_view{ r2 };
            std::cout << "accumulate: " << std::accumulate(c2.begin(),
       c2.end(), 0) << '\n';

            // inherited from ranges::view_interface:
            std::cout << "c2.front(): " << c2.front() << '\n';
        //  auto e3 = c2.back(); // error: "bidirectional range" required
        //  auto e4 = c2.data(); // error: "contiguous range" required
        //  auto e5 = c2[0];     // error: "random access range" required
        }

⭐ Possible output: ⭐

        accumulate: 15
        c1.front(): 1
        c1.back(): 5
        c1.data(): 0x7f19937f00d0
        c1[0]: 1
        accumulate: 15
        c2.front(): 1

πŸ’€ Defect reports πŸ’€

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

  • LWG 3494, applied to C++20 β€” behavior as published: common_view was never a borrowed_range; correct behavior: it is a borrowed_range if its underlying view is.

🌈 See also 🌈

  • ranges::common_range (C++20) β€” specifies that a range has identical iterator and sentinel types (concept)
  • common_iterator (C++20) β€” adapts an iterator type and its sentinel into a common iterator type (class template)

and that's the page, bestie 🫢 source/version + date: http://cppreference.com, 2024.06.10, and the page id is std::ranges...:common_view(3). mwah πŸ’‹βœ¨

πŸ“¦ where this page comes from