std::ranges::constant_range - cppreference.com (original) (raw)

Defined in header
template< class T > concept constant_range = ranges::input_range<T> && /*constant-iterator*/<ranges::iterator_t<T>>; (1) (since C++23)
Helper concepts
template< class T > concept /*constant-iterator*/ = std::input_iterator<T> && std::same_as<std::iter_const_reference_t<T>, std::iter_reference_t<T>>; (2) (exposition only*)
  1. The constant_range concept is a refinement of range for which ranges::begin returns a constant iterator.

  2. The concept /*constant-iterator*/<T> is satisfied when the result of the indirection operation of the input iterator is its const reference type which implies read-only.

[edit] Example

#include #include #include #include   // mechanisms for ensuring the parameter is a constant range // 1) an overload set where the mutable one defers to the constant one template<std::ranges::constant_range R> void takes_any_range1(R&& r) { // R is definitely a constant range }   template<std::ranges::range R> void takes_any_range1(R&& r) { takes_any_range1(std::views::as_const(std::forward(r))); }   // 2) one function template that shadows its parameter template<std::ranges::range R> void takes_any_range2(R&& _r) { auto r = std::views::as_const(std::forward(_r));   // r is definitely a constant range // never use _r again }   // 3) one function template that recursively invokes itself template<std::ranges::range R> void takes_any_range3(R&& r) { if constexpr (std::ranges::constant_range) { // R is definitely a constant range // put implementation here } else takes_any_range3(std::views::as_const(std::forward(r))); }   static_assert ( std::ranges::constant_range<const std::vector> and not std::ranges::constant_range<std::vector> and std::ranges::constant_range<std::string_view> and not std::ranges::constant_range<std::span> and std::ranges::constant_range<std::span> and not std::ranges::constant_range<const std::span> );   int main() {}