Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/ranges/range"

From cppreference.com
< cpp‎ | ranges
(mention how to make a class satisfy this concept)
m (Example: {{source}} => {{example}} to enable online experiments.)
 
(3 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
{{cpp/ranges/title|range}}
 
{{cpp/ranges/title|range}}
 
{{cpp/ranges/navbar}}
 
{{cpp/ranges/navbar}}
 
+
{{ddcl|header=ranges|since=c++20|1=
{{dcl begin}}
+
{{dcl header|ranges}}
+
{{dcl|since=c++20|1=
+
 
template< class T >
 
template< class T >
 
concept range = requires( T& t ) {
 
concept range = requires( T& t ) {
  ranges::begin(t); // equality-preserving for forward iterators
+
    ranges::begin(t); // equality-preserving for forward iterators
  ranges::end (t);
+
    ranges::end (t);
 
};
 
};
 
}}
 
}}
{{dcl end}}
 
  
 
The {{tt|range}} concept defines the requirements of a type that allows iteration over its elements by providing an iterator and sentinel that denote the elements of the range.
 
The {{tt|range}} concept defines the requirements of a type that allows iteration over its elements by providing an iterator and sentinel that denote the elements of the range.
  
 
===Semantic requirements===
 
===Semantic requirements===
Given an expression {{c|E}} such that {{c|decltype((E))}} is {{c|T}}, {{c|T}} models {{c|range}} only if
+
Given an expression {{c|E}} such that {{c/core|decltype((E))}} is {{tt|T}}, {{tt|T}} models {{tt|range}} only if
* [{{c|ranges::begin(E)}}, {{c|ranges::end(E)}}) denotes a range, and
+
* {{range|ranges::begin(E)|ranges::end(E)}} denotes a [[cpp/iterator#Ranges|range]], and
 
* both {{c|ranges::begin(E)}} and {{c|ranges::end(E)}} are amortized constant time and do not alter the value of {{c|E}} in a manner observable to [[cpp/concepts#Equality preservation|equality-preserving]] expressions, and
 
* both {{c|ranges::begin(E)}} and {{c|ranges::end(E)}} are amortized constant time and do not alter the value of {{c|E}} in a manner observable to [[cpp/concepts#Equality preservation|equality-preserving]] expressions, and
 
* if the type of {{c|ranges::begin(E)}} models {{lconcept|forward_iterator}}, {{c|ranges::begin(E)}} is [[cpp/concepts#Equality preservation|equality-preserving]] (in other words, forward iterators support multi-pass algorithms).
 
* if the type of {{c|ranges::begin(E)}} models {{lconcept|forward_iterator}}, {{c|ranges::begin(E)}} is [[cpp/concepts#Equality preservation|equality-preserving]] (in other words, forward iterators support multi-pass algorithms).
Note: In the definition above, the required expressions {{c|1=ranges::begin(t)}} and {{c|1=ranges::end(t)}} do not require [[cpp/concepts/equality_comparable#Implicit expression variations|implicit expression variations]].
 
  
 
===Notes===
 
===Notes===
Line 33: Line 28:
 
{{example
 
{{example
 
|code=
 
|code=
#include <iostream>
 
 
#include <ranges>
 
#include <ranges>
#include <vector>
+
 
+
// A minimum range
template <typename T>
+
struct SimpleRange
struct range_t : private T
+
 
{
 
{
     using T::begin, T::end; /*...*/
+
     int* begin();
 +
    int* end();
 
};
 
};
static_assert(std::ranges::range< range_t<std::vector<int>> >);
+
static_assert(std::ranges::range<SimpleRange>);
  
template <typename T> struct scalar_t
+
// Not a range: no begin/end
 +
struct NotRange
 
{
 
{
     T t {}; /* no begin/end */
+
     int t {};
 
};
 
};
static_assert(not std::ranges::range< scalar_t<int> >);
+
static_assert(!std::ranges::range<NotRange>);
+
 
int main()
+
// Not a range: begin does not return an input_or_output_iterator
 +
struct NotRange2
 
{
 
{
     if constexpr (range_t<std::vector<int>> r; std::ranges::range<decltype(r)>)
+
     void* begin();
        std::cout << "r is a range\n";
+
    int* end();
 +
};
 +
static_assert(!std::ranges::range<NotRange2>);
  
    if constexpr (scalar_t<int> s; not std::ranges::range<decltype(s)>)
+
int main() {}
        std::cout << "s is not a range\n";
+
}
+
|output=
+
r is a range
+
s is not a range
+
 
}}
 
}}
 +
 +
===Defect reports===
 +
{{dr list begin}}
 +
{{dr list item|wg=lwg|dr=3915|std=C++20|before={{c|ranges::begin(t)}} and {{c|ranges::end(t)}}<br>did not require implicit expression variations|after=removed the<br>redundant description}}
 +
{{dr list end}}
  
 
{{langlinks|es|ja|ru|zh}}
 
{{langlinks|es|ja|ru|zh}}

Latest revision as of 07:54, 25 July 2024

 
 
Ranges library
Range adaptors
 
Defined in header <ranges>
template< class T >

concept range = requires( T& t ) {
    ranges::begin(t); // equality-preserving for forward iterators
    ranges::end (t);

};
(since C++20)

The range concept defines the requirements of a type that allows iteration over its elements by providing an iterator and sentinel that denote the elements of the range.

Contents

[edit] Semantic requirements

Given an expression E such that decltype((E)) is T, T models range only if

[edit] Notes

A typical range class only needs to provide two functions:

  1. A member function begin() whose return type models input_or_output_iterator.
  2. A member function end() whose return type models sentinel_for<It>, where It is the return type of begin().

Alternatively, they can be non-member functions, to be found by argument-dependent lookup.

[edit] Example

#include <ranges>
 
// A minimum range
struct SimpleRange
{
    int* begin();
    int* end();
};
static_assert(std::ranges::range<SimpleRange>);
 
// Not a range: no begin/end
struct NotRange
{
    int t {};
};
static_assert(!std::ranges::range<NotRange>);
 
// Not a range: begin does not return an input_or_output_iterator
struct NotRange2
{
    void* begin();
    int* end();
};
static_assert(!std::ranges::range<NotRange2>);
 
int main() {}

[edit] Defect reports

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

DR Applied to Behavior as published Correct behavior
LWG 3915 C++20 ranges::begin(t) and ranges::end(t)
did not require implicit expression variations
removed the
redundant description