The View concept specifies the requirements of a Range type that has constant time copy, move and assignment operators; that is, the cost of these operations is not proportional to the number of elements in the View.
[ Example: Examples of Views are:
A Range type that wraps a pair of iterators.
A Range type that holds its elements by shared_ptr and shares ownership with all its copies.
A Range type that generates its elements on demand.
A container ( ISO/IEC 14882:2014 §[containers]) is not a View since copying the container copies the elements, which cannot be done in constant time. — end example ]
template <class T>
constexpr bool view-predicate // exposition only
= see below;
template <class T>
concept bool View =
Range<T> &&
Semiregular<T> &&
view-predicate<T>;
Since the difference between Range and View is largely semantic, the two are differentiated with the help of the enable_view trait. Users may specialize enable_view to derive from true_type or false_type.
For a type T, the value of view-predicate<T> shall be:
If enable_view<T> has a member type type, enable_view<T>::type::value;
Otherwise, if T is derived from view_base, true;
Otherwise, if T is an instantiation of class template initializer_list ( ISO/IEC 14882:2014 §[support.initlist]), set ( ISO/IEC 14882:2014 §[set]), multiset ( ISO/IEC 14882:2014 §[multiset]), unordered_set ( ISO/IEC 14882:2014 §[unord.set]), or unordered_multiset ( ISO/IEC 14882:2014 §[unord.multiset]), false;
Otherwise, if both T and const T satisfy Range and reference_t<iterator_t<T>> is not the same type as reference_t<iterator_t<const T>>, false; [ Note: Deep const-ness implies element ownership, whereas shallow const-ness implies reference semantics. — end note ]
Otherwise, true.