Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/ranges/view"

From cppreference.com
< cpp‎ | ranges
(Notes: more from P2415R1)
m (added specializations section)
 
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{cpp/ranges/title | view | enable_view | view_base }}
+
{{cpp/ranges/title|view|enable_view|view_base}}
 
{{cpp/ranges/navbar}}
 
{{cpp/ranges/navbar}}
  
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | ranges}}
+
{{dcl header|ranges}}
 
{{dcl|num=1|since=c++20|1=
 
{{dcl|num=1|since=c++20|1=
 
template<class T>
 
template<class T>
Line 10: Line 10:
 
{{dcl|num=2|since=c++20|1=
 
{{dcl|num=2|since=c++20|1=
 
template<class T>
 
template<class T>
inline constexpr bool enable_view =
+
constexpr bool enable_view =
 
     std::derived_from<T, view_base> {{!!}} /*is-derived-from-view-interface*/<T>;
 
     std::derived_from<T, view_base> {{!!}} /*is-derived-from-view-interface*/<T>;
 
}}
 
}}
Line 21: Line 21:
  
 
@2@ The {{tt|enable_view}} variable template is used to indicate whether a {{lconcept|range}} is a {{tt|view}}. {{c|/*is-derived-from-view-interface*/<T>}} is {{c|true}} if and only if {{tt|T}} has exactly one public base class {{c|ranges::view_interface<U>}} for some type {{tt|U}}, and {{tt|T}} has no base classes of type {{c|ranges::view_interface<V>}} for any other type {{tt|V}}.
 
@2@ The {{tt|enable_view}} variable template is used to indicate whether a {{lconcept|range}} is a {{tt|view}}. {{c|/*is-derived-from-view-interface*/<T>}} is {{c|true}} if and only if {{tt|T}} has exactly one public base class {{c|ranges::view_interface<U>}} for some type {{tt|U}}, and {{tt|T}} has no base classes of type {{c|ranges::view_interface<V>}} for any other type {{tt|V}}.
<br>Users may specialize {{tt|enable_view}} to {{c|true}} for cv-unqualified program-defined types which model {{tt|view}}, and {{c|false}} for types which do not. Such specializations must be [[cpp/language/constant expression#Usable in constant expressions|usable in constant expressions]] and have type {{c|const bool}}.
+
<br>Users may specialize {{tt|enable_view}} to {{c|true}} for cv-unqualified program-defined types which model {{tt|view}}, and {{c|false}} for types which do not. Such specializations must be [[cpp/language/constant expression#Usable in constant expressions|usable in constant expressions]] and have type {{c/core|const bool}}.
  
 
@3@ Deriving from {{tt|view_base}} enables {{lconcept|range}} types to model {{tt|view}}.
 
@3@ Deriving from {{tt|view_base}} enables {{lconcept|range}} types to model {{tt|view}}.
Line 31: Line 31:
 
* either {{c|std::copy_constructible<T>}} is {{c|false}}, or copy construction of {{tt|T}} has constant time complexity, and
 
* either {{c|std::copy_constructible<T>}} is {{c|false}}, or copy construction of {{tt|T}} has constant time complexity, and
 
* either {{c|std::copyable<T>}} is {{c|false}}, or copy assignment of {{tt|T}} has no more time complexity than destruction followed by copy construction.
 
* either {{c|std::copyable<T>}} is {{c|false}}, or copy assignment of {{tt|T}} has no more time complexity than destruction followed by copy construction.
 +
 +
===Specializations===
 +
Specializations of {{tt|enable_view}} for all specializations of the following standard templates are defined as {{c|true}}:
 +
* {{ltt|cpp/string/basic_string_view|std::basic_string_view}}
 +
* {{ltt|cpp/container/span|std::span}}
 +
{{rrev|since=c++26|1=
 +
* {{ltt|cpp/utility/optional|std::optional}}
 +
}}
  
 
===Notes===
 
===Notes===
Line 40: Line 48:
 
A copyable container such as {{c|std::vector<std::string>}} generally does not meet the semantic requirements of {{tt|view}} since copying the container copies all of the elements, which cannot be done in constant time.
 
A copyable container such as {{c|std::vector<std::string>}} generally does not meet the semantic requirements of {{tt|view}} since copying the container copies all of the elements, which cannot be done in constant time.
  
While views were originally described as cheaply copyable and non-owning ranges, a type is not required to be copyable or non-owning for it to model {{tt|view}}. However, it must still be cheap to copy (if ever possible), move, assign, and destroy, so that [[cpp/ranges#Range_adaptors|range adaptors]] will not have unexpected complexity.
+
While views were originally described as cheaply copyable and non-owning ranges, a type is not required to be copyable or non-owning for it to model {{tt|view}}. However, it must still be cheap to copy (if it is copyable), move, assign, and destroy, so that {{lsd|cpp/ranges#Range adaptors}} will not have unexpected complexity.
  
 
By default, a type modeling {{lconcept|movable}} and {{lconcept|range}} is considered a view if it is publicly and unambiguously derived from {{tt|view_base}}, or exactly one specialization of {{lc|std::ranges::view_interface}}.
 
By default, a type modeling {{lconcept|movable}} and {{lconcept|range}} is considered a view if it is publicly and unambiguously derived from {{tt|view_base}}, or exactly one specialization of {{lc|std::ranges::view_interface}}.
 +
 +
===Example===
 +
A minimum view.
 +
 +
{{source|1=
 +
#include <ranges>
 +
 +
struct ArchetypalView : std::ranges::view_interface<ArchetypalView>
 +
{
 +
    int* begin();
 +
    int* end();
 +
};
 +
 +
static_assert(std::ranges::view<ArchetypalView>);
 +
}}
  
 
===Defect reports===
 
===Defect reports===

Latest revision as of 17:44, 2 July 2024

 
 
Ranges library
Range adaptors
 
Defined in header <ranges>
template<class T>
concept view = ranges::range<T> && std::movable<T> && ranges::enable_view<T>;
(1) (since C++20)
template<class T>

constexpr bool enable_view =

    std::derived_from<T, view_base> || /*is-derived-from-view-interface*/<T>;
(2) (since C++20)
struct view_base { };
(3) (since C++20)
1) The view concept specifies the requirements of a range type that has suitable semantic properties for use in constructing range adaptor pipelines.
2) The enable_view variable template is used to indicate whether a range is a view. /*is-derived-from-view-interface*/<T> is true if and only if T has exactly one public base class ranges::view_interface<U> for some type U, and T has no base classes of type ranges::view_interface<V> for any other type V.
Users may specialize enable_view to true for cv-unqualified program-defined types which model view, and false for types which do not. Such specializations must be usable in constant expressions and have type const bool.
3) Deriving from view_base enables range types to model view.

Contents

[edit] Semantic requirements

1) T models view only if:
  • move construction of T has constant time complexity, and
  • if N copies and/or moves are made from a T object holding M elements, then these N objects have 𝓞(N+M) destruction (which implies that a moved-from view object has 𝓞(1) destruction), and
  • either std::copy_constructible<T> is false, or copy construction of T has constant time complexity, and
  • either std::copyable<T> is false, or copy assignment of T has no more time complexity than destruction followed by copy construction.

[edit] Specializations

Specializations of enable_view for all specializations of the following standard templates are defined as true:

(since C++26)

[edit] Notes

Examples of view types are:

A copyable container such as std::vector<std::string> generally does not meet the semantic requirements of view since copying the container copies all of the elements, which cannot be done in constant time.

While views were originally described as cheaply copyable and non-owning ranges, a type is not required to be copyable or non-owning for it to model view. However, it must still be cheap to copy (if it is copyable), move, assign, and destroy, so that range adaptors will not have unexpected complexity.

By default, a type modeling movable and range is considered a view if it is publicly and unambiguously derived from view_base, or exactly one specialization of std::ranges::view_interface.

[edit] Example

A minimum view.

#include <ranges>
 
struct ArchetypalView : std::ranges::view_interface<ArchetypalView>
{
    int* begin();
    int* end();
};
 
static_assert(std::ranges::view<ArchetypalView>);

[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
P2325R3 C++20 view required default_initializable does not require
LWG 3549 C++20 enable_view did not detect inheritance from view_interface detects
P2415R2 C++20 the restriction on the time complexity of destruction was too strict relaxed