Espacios de nombres
Variantes
Acciones

Archivo de encabezado de la biblioteca estándar <ranges>

De cppreference.com
< cpp‎ | header
 
 
Archivos de encabezado de la biblioteca estándar
 

Este encabezado es parte de la bibloteca de ranges.

Contenido

[editar] Alias de espacios de nombres

namespace std {

    namespace views = ranges::views;

}

El alias del espacio de nombres std::views se proporciona como una abreviatura de std::ranges::views.

Conceptos

Conceptos de rangos
Definido en el espacio de nombres std::ranges
Especifica que un tipo es un rango. Es decir, proporciona un iterador begin y un centinela end.
(concepto) [editar]
Especifica que un tipo es un rango (range) e iteradores obtenidos a partir de una expresión de él pueden devolverse de forma segura sin peligro de que queden pendientes.
(concepto) [editar]
Especifica que un rango conoce su tamaño en tiempo constante.
(concepto) [editar]
Especifica que un rango es una vista. Es decir, realiza copia, movimiento y asignación en tiempo constante.
(concepto) [editar]
Especifica un rango cuyo tipo de iterador satisface a input_iterator.
(concepto) [editar]
Especifica un rango cuyo tipo de iterador satisface a output_iterator.
(concepto) [editar]
Especifica un rango cuyo tipo de iterador satisface a forward_iterator.
(concepto) [editar]
Especifica un rango cuyo tipo de iterador satisface a bidirectional_iterator.
(concepto) [editar]
Especifica un rango cuyo tipo de iterador satisface a random_access_iterator.
(concepto) [editar]
Especifica un rango cuyo tipo de iterador satisface a contiguous_iterator.
(concepto) [editar]
Especifica que un rango tiene tipos de iterador y centinela idénticos.
(concepto) [editar]
Especifica los requerimientos para un rango (range) para que sea convertible de forma segura a una vista (view).
(concepto) [editar]

Clases

Primitivas de rangos
Definido en el espacio de nombres std::ranges
Obtiene los tipos asociados de un rango.
(plantilla de alias) [editar]
Vistas
Definido en el espacio de nombres std::ranges
Plantilla de clase auxiliar para definir una vista (view), usando el patrón de plantilla curiosamente recurrente (CRTP).
(plantilla de clase) [editar]
Combina un par iterador-centinela en una vista (view).
(plantilla de clase) [editar]
Manejo de iteradores pendientes
Definido en el espacio de nombres std::ranges
Un tipo marcador de posición que indica que un iterador o un subrango (subrange) no debe devolverse ya que quedaría pendiente.
(clase) [editar]
Obtiene el tipo iterador o tipo subrango (subrange) de un rango prestado (borrowed_range).
(plantilla de alias) [editar]
Fábricas
Definido en el espacio de nombres std::ranges
Una vista (view) sin elementos.
(plantilla de clase) (plantilla de variables) [editar]
Una vista (view) que contiene un solo elemento de un valor específico.
(plantilla de clase) (objeto punto de personalización) [editar]
Una vista (view) que consiste en una secuencia generada al incrementar repetidamente un valor inicial.
(plantilla de clase) (objeto punto de personalización) [editar]
Una vista (view) que consiste en los elementos obtenidos mediante la aplicación sucesiva del operador de extracción (operator>>) sobre el flujo de entrada asociado.
(plantilla de clase) (objeto punto de personalización) [editar]
Adaptadores
Definido en el espacio de nombres std::ranges
Una vista (view) que incluye todos los elementos de un rango (range).
(plantilla de alias) (objeto adaptador de rango) [editar]
Una vista (view) de los elementos de algún otro rango (range).
(plantilla de clase) [editar]
Una vista (view) con propiedad única de algún rango (range).
(plantilla de clase) [editar]
Una vista (view) que consiste en los elementos de un rango (range) que satisface un predicado.
(plantilla de clase) (objeto adaptador de rango) [editar]
Una vista (view) de una secuencia que aplica una función de transformación a cada elemento.
(plantilla de clase) (objeto adaptador de rango) [editar]
Una vista (view) que consiste de los primeros N elementos de otra vista.
(plantilla de clase) (objeto adaptador de rango) [editar]
Una vista (view) que consiste en los elementos iniciales de otra vista, hasta el primer elemento sobre el que un predicado devuelva falso.
(plantilla de clase) (objeto adaptador de rango) [editar]
Una vista (view) que consiste en los elementos de otra vista, saltándose los primeros N elementos.
(plantilla de clase) (objeto adaptador de rango) [editar]
Una vista (view) que consiste en los elementos de otra vista, saltándose la subsecuencia inicial de elementos hasta el primer elemento donde el predicado devuelva falso.
(plantilla de clase) (objeto adaptador de rango) [editar]
Una vista (view) que consiste en la secuencia obtenida al aplanar una vista de rangos (range).
(plantilla de clase) (objeto adaptador de rango) [editar]
Una vista (view) sobre los subrangos obtenidos al separar otra vista (view) usando un delimitador.
(plantilla de clase) (objeto adaptador de rango) [editar]
Una vista (view) sobre los subrangos obtenidos al dividir otra vista usando un delimitador.
(plantilla de clase) (objeto adaptador de rango) [editar]
Crea un subrango a partir de un iterador y una cuenta.
(objeto punto de personalización) [editar]
Convierte una vista (view) a un rango común (common_range).
(plantilla de clase) (objeto adaptador de rango) [editar]
Una vista (view) que itera sobre los elementos de otra vista bidirectional en orden inverso.
(plantilla de clase) (objeto adaptador de rango) [editar]
Toma una vista (view) que consiste en valores similares a tuplas y a un número N y produce una vista del N-ésimo elemento de cada tupla.
(plantilla de clase) (objeto adaptador de rango) [editar]
Toma una vista (view) que consiste en valores similares a pares y produce una vista de los primeros elementos de cada par.
(plantilla de clase) (objeto adaptador de rango) [editar]
Toma una vista (view) que consiste valores similares a pares y produce una vista de los segundos elementos de cada par.
(plantilla de clase) (objeto adaptador de rango) [editar]
Una vista (view) que consiste en tuplas o referencias a elementos correspondientes de las vistas adaptadas.
(plantilla de clase) (objeto punto de personalización) [editar]
Una vista (view) que consiste en tuplas del resultado de aplicar una función de transformación a los elementos correspondientes de las vistas adaptadas.
(plantilla de clase) (objeto punto de personalización) [editar]
Una vista (view) que consiste en tuplas de referencias a elementos adyacentes de la vista adaptada.
(plantilla de clase) (objeto adaptador de rango) [editar]
Una vista (vista) que consiste en tuplas del resultado de aplicar una función de transformación a elementos adyacentes de la vista adaptada.
(plantilla de clase) (objeto adaptador de rango) [editar]

Objetos de punto de personalización

Acceso a rangos
Definido en el espacio de nombres std::ranges
Devuelve un iterador al principio de un rango.
(objeto punto de personalización) [editar]
Devuelve un iterador al final de un rango
(objeto punto de personalización) [editar]
Devuelve un iterador al inicio de un rango de solo lectura.
(objeto punto de personalización) [editar]
Devuelve un centinela que indica el fin de un rango de solo lectura
(objeto punto de personalización) [editar]
Devuelve un iterador inverso a un rango
(objeto punto de personalización) [editar]
Devuelve un iterador final inverso a un rango
(objeto punto de personalización) [editar]
Devuelve un iterador inverso a un rango de solo lectura
(objeto punto de personalización) [editar]
Devuelve un iterador inverso al final de un rango de solo lectura
(objeto punto de personalización) [editar]
Obtiene el tamaño de un rango cuyo tamaño puede calcularse en tiempo constante.
(objeto punto de personalización) [editar]
Obtiene el tamaño de un rango cuyo tamaño puede calcularse en tiempo constante y lo convierte a un entero con signo.
(objeto punto de personalización) [editar]
Comprueba si un rango está vacío.
(objeto punto de personalización) [editar]
Obtiene un puntero al principio de un rango contiguo
(objeto punto de personalización) [editar]
Obtiene un puntero al inicio de un rango contiguo de solo lectura
(objeto punto de personalización) [editar]

Enumeraciones

Definido en el espacio de nombres std::ranges
Especifica si un subrango (std::ranges::subrange) modela std::ranges::sized_range.
(enum) [editar]

[editar] Sinopsis

#include <compare>
#include <initializer_list>
#include <iterator>
 
namespace std::ranges {
  inline namespace /* no especificado */ {
    // range access
    inline constexpr /* no especificado */ begin   = /* no especificado */;
    inline constexpr /* no especificado */ end     = /* no especificado */;
    inline constexpr /* no especificado */ cbegin  = /* no especificado */;
    inline constexpr /* no especificado */ cend    = /* no especificado */;
    inline constexpr /* no especificado */ rbegin  = /* no especificado */;
    inline constexpr /* no especificado */ rend    = /* no especificado */;
    inline constexpr /* no especificado */ crbegin = /* no especificado */;
    inline constexpr /* no especificado */ crend   = /* no especificado */;
 
    inline constexpr /* no especificado */ size    = /* no especificado */;
    inline constexpr /* no especificado */ ssize   = /* no especificado */;
    inline constexpr /* no especificado */ empty   = /* no especificado */;
    inline constexpr /* no especificado */ data    = /* no especificado */;
    inline constexpr /* no especificado */ cdata   = /* no especificado */;
  }
 
  // ranges
  template<class T>
    concept range = /* véase descripción */;
 
  template<class T>
    inline constexpr bool enable_borrowed_range = false;
 
  template<class T>
    concept borrowed_range = /* véase descripción */;
 
  template<class T>
    using iterator_t = decltype(ranges::begin(declval<T&>()));
  template<range R>
    using sentinel_t = decltype(ranges::end(declval<R&>()));
  template<range R>
    using range_difference_t = iter_difference_t<iterator_t<R>>;
  template<sized_range R>
    using range_size_t = decltype(ranges::size(declval<R&>()));
  template<range R>
    using range_value_t = iter_value_t<iterator_t<R>>;
  template<range R>
    using range_reference_t = iter_reference_t<iterator_t<R>>;
  template<range R>
    using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<R>>;
 
  // rangos con tamaño
  template<class>
    inline constexpr bool disable_sized_range = false;
 
  template<class T>
    concept sized_range = /* véase descripción */;
 
  // vistas
  template<class T>
    inline constexpr bool enable_view = /* véase descripción */;
 
  struct view_base {};
 
  template<class T>
    concept view = /* véase descripción */;
 
  // otros refinamientos de rangos
  template<class R, class T>
    concept output_range = /* véase descripción */;
 
  template<class T>
    concept input_range = /* véase descripción */;
 
  template<class T>
    concept forward_range = /* véase descripción */;
 
  template<class T>
    concept bidirectional_range = /* véase descripción */;
 
  template<class T>
    concept random_access_range = /* véase descripción */;
 
  template<class T>
    concept contiguous_range = /* véase descripción */;
 
  template<class T>
    concept common_range = /* véase descripción */;
 
  template<class T>
    concept viewable_range = /* véase descripción */;
 
  // plantilla de clase view_interface
  template<class D>
    requires is_class_v<D> && same_as<D, remove_cv_t<D>>
  class view_interface;
 
  // subrangos
  enum class subrange_kind : bool { unsized, sized };
 
  template<input_or_output_iterator I, sentinel_for<I> S = I,
           subrange_kind K = /* véase descripción */>
    requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
  class subrange;
 
  template<class I, class S, subrange_kind K>
    inline constexpr bool enable_borrowed_range<subrange<I, S, K>> = true;
 
  // manejo de iteradores pendientes
  struct dangling;
 
  template<range R>
    using borrowed_iterator_t = /* véase descripción */;
 
  template<range R>
    using borrowed_subrange_t = /* véase descripción */;
 
  // vista vacía
  template<class T>
    requires is_object_v<T>
  class empty_view;
 
  template<class T>
    inline constexpr bool enable_borrowed_range<empty_view<T>> = true;
 
  namespace views {
    template<class T>
      inline constexpr empty_view<T> empty{};
  }
 
  // vista única
  template<copy_constructible T>
    requires is_object_v<T>
  class single_view;
 
  namespace views { inline constexpr /* no especificado */ single = /* no especificado */; }
 
  template<bool Const, class T>
    using /*maybe_const*/ = conditional_t<Const, const T, T>;   // solo exposición
 
  // vista iota
  template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t>
    requires /*weakly_equality_comparable_with*/<W, Bound> && copyable<W>
  class iota_view;
 
  template<class W, class Bound>
    inline constexpr bool enable_borrowed_range<iota_view<W, Bound>> = true;
 
  namespace views { inline constexpr /* no especificado */ iota = /* no especificado */; }
 
  // istream view
  template<movable Val, class CharT, class Traits = char_traits<CharT>>
    requires /* véase descripción */
  class basic_istream_view;
  template<class Val>
    using istream_view = basic_istream_view<Val, char>;
  template<class Val>
    using wistream_view = basic_istream_view<Val, wchar_t>;
 
  namespace views {
    template<class T>
      inline constexpr /* no especificado */ istream = /* no especificado */; }
 
  // vista all
  namespace views {
    inline constexpr /* no especificado */ all = /* no especificado */;
 
    template<viewable_range R>
      using all_t = decltype(all(declval<R>()));
  }
 
  template<range R>
    requires is_object_v<R>
  class ref_view;
 
  template<class T>
    inline constexpr bool enable_borrowed_range<ref_view<T>> = true;
 
  // vista owning_view 
  template<range R>
    requires /* véase descripción */
  class owning_view;
 
  template<class T>
    inline constexpr bool enable_borrowed_range<owning_view<T>> =
                          enable_borrowed_range<T>;
  // vista filter_view
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
    requires view<V> && is_object_v<Pred>
  class filter_view;
 
  namespace views { inline constexpr /* no especificado */ filter = /* no especificado */; }
 
  // vista transform_view
  template<input_range V, copy_constructible F>
    requires view<V> && is_object_v<F> &&
             regular_invocable<F&, range_reference_t<V>> &&
             /*can_reference*/<invoke_result_t<F&, range_reference_t<V>>>
  class transform_view;
 
  namespace views { inline constexpr /* no especificado */ transform = /* no especificado */; }
 
  // vista take_view
  template<view> class take_view;
 
  template<class T>
    inline constexpr bool enable_borrowed_range<take_view<T>> = enable_borrowed_range<T>;
 
  namespace views { inline constexpr /* no especificado */ take = /* no especificado */; }
 
  // vista take_while_view
  template<view V, class Pred>
    requires input_range<V> && is_object_v<Pred> &&
             indirect_unary_predicate<const Pred, iterator_t<V>>
    class take_while_view;
 
  namespace views { inline constexpr /* no especificado */ take_while = /* no especificado */; }
 
  // vista drop_view
  template<view V>
    class drop_view;
 
  template<class T>
    inline constexpr bool enable_borrowed_range<drop_view<T>> = enable_borrowed_range<T>;
 
  namespace views { inline constexpr /* no especificado */ drop = /* no especificado */; }
 
  // vista drop_while_view
  template<view V, class Pred>
    requires input_range<V> && is_object_v<Pred> &&
             indirect_unary_predicate<const Pred, iterator_t<V>>
    class drop_while_view;
 
  template<class T, class Pred>
    inline constexpr bool enable_borrowed_range<drop_while_view<T, Pred>> =
      enable_borrowed_range<T>;
 
  namespace views { inline constexpr /* no especificado */ drop_while = /* no especificado */; }
 
  // vista join_view
  template<input_range V>
    requires view<V> && input_range<range_reference_t<V>>
  class join_view;
 
  namespace views { inline constexpr /* no especificado */ join = /* no especificado */; }
 
  // vista lazy_split_view
  template<class R>
    concept /*tiny_range*/ = /* véase descripción */;   // solo exposición
 
  template<input_range V, forward_range Pattern>
    requires view<V> && view<Pattern> &&
             indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
             && (forward_range<V> || /*tiny_range*/<Pattern>)
  class lazy_split_view;
 
  // vista split_view
 template<forward_range V, forward_range Pattern>
   requires view<V> && view<Pattern> &&
            indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
  class split_view;
 
  namespace views {
    inline constexpr /* no especificado */ lazy_split = /* no especificado */;
    inline constexpr /* no especificado */ split = /* no especificado */;
  }
 
  // vista counted
  namespace views { inline constexpr /* no especificado */ counted = /* no especificado */; }
 
  // vista common_view
  template<view V>
    requires (!common_range<V> && copyable<iterator_t<V>>)
  class common_view;
 
  template<class T>
    inline constexpr bool enable_borrowed_range<common_view<T>> =
      enable_borrowed_range<T>;
 
  namespace views { inline constexpr /* no especificado */ common = /* no especificado */; }
 
  // vista reverse_view
  template<view V>
    requires bidirectional_range<V>
  class reverse_view;
 
  template<class T>
    inline constexpr bool enable_borrowed_range<reverse_view<T>> =
      enable_borrowed_range<T>;
 
  namespace views { inline constexpr /* no especificado */ reverse = /* no especificado */; }
 
  // vista elements_view
  template<input_range V, size_t N>
    requires /* véase descripción */
  class elements_view;
 
  template<class T, size_t N>
    inline constexpr bool enable_borrowed_range<elements_view<T, N>> =
      enable_borrowed_range<T>;
 
  template<class R>
    using keys_view = elements_view<R, 0>;
  template<class R>
    using values_view = elements_view<R, 1>;
 
  namespace views {
    template<size_t N>
      inline constexpr /* no especificado */ elements = /* no especificado */;
    inline constexpr auto keys = elements<0>;
    inline constexpr auto values = elements<1>;
  }
 
  // vista zip_view
  template<input_range... Views>
    requires (view<Views> && ...) && (sizeof...(Views) > 0)
  class zip_view;
 
  template<class... Views>
    inline constexpr bool enable_borrowed_range<zip_view<Views...>> =
      (enable_borrowed_range<Views> && ...);
 
  namespace views { inline constexpr /* no especificado */ zip = /* no especificado */; }
 
  // vista zip_transform_view
  template<copy_constructible F, input_range... Views>
    requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
             regular_invocable<F&, range_reference_t<Views>...> &&
             /*can_reference*/<invoke_result_t<F&, range_reference_t<Views>...>>
  class zip_transform_view;
 
  namespace views { inline constexpr /* no especificado */ zip_transform =
    /* no especificado */; }
 
  // vista adjacent_view
  template<forward_range V, size_t N>
    requires view<V> && (N > 0)
  class adjacent_view;
 
  template<class V, size_t N>
    inline constexpr bool enable_borrowed_range<adjacent_view<V, N>> =
      enable_borrowed_range<V>;
 
  namespace views {
    template<size_t N>
      inline constexpr /* no especificado */ adjacent = /* no especificado */ ;
    inline constexpr auto pairwise = adjacent<2>;
  }
 
  // vista adjacent_transform_view
  template<forward_range V, copy_constructible F, size_t N>
    requires /* véase descripción */
  class adjacent_transform_view;
 
  namespace views {
    template<size_t N>
      inline constexpr /* no especificado */ adjacent_transform = /* no especificado */;
    inline constexpr auto pairwise_transform = adjacent_transform<2>;
  }
}
 
namespace std {
  namespace views = ranges::views;
 
  template<class T> struct tuple_size;
  template<size_t I, class T> struct tuple_element;
 
  template<class I, class S, ranges::subrange_kind K>
  struct tuple_size<ranges::subrange<I, S, K>>
    : integral_constant<size_t, 2> {};
  template<class I, class S, ranges::subrange_kind K>
  struct tuple_element<0, ranges::subrange<I, S, K>> {
    using type = I;
  };
  template<class I, class S, ranges::subrange_kind K>
  struct tuple_element<1, ranges::subrange<I, S, K>> {
    using type = S;
  };
  template<class I, class S, ranges::subrange_kind K>
  struct tuple_element<0, const ranges::subrange<I, S, K>> {
    using type = I;
  };
  template<class I, class S, ranges::subrange_kind K>
  struct tuple_element<1, const ranges::subrange<I, S, K>> {
    using type = S;
  };
}

[editar] Concepto range

namespace std::ranges {
  template< class T >
    concept range = requires(T& t) {
      ranges::begin(t); // conservador de la igualdad para iteradores de avance
      ranges::end(t);
  };
}

[editar] Concepto sized_range

namespace std::ranges {
  template< class T >
    concept sized_range = range<T> &&
      requires(T& t) {
        ranges::size(t);
      };
}

[editar] Concepto view

namespace std::ranges {
  template<class T>
    inline constexpr bool enable_view = derived_from<T, view_base>;
 
  template<class T>
    concept view = range<T>
                && movable<T>
                && enable_view<T>;
}

[editar] Concepto output_range

namespace std::ranges {
  template<class R, class T>
    concept output_range =
      range<R> && output_iterator<iterator_t<R>, T>;
}

[editar] Concepto input_range

namespace std::ranges {
  template<class T>
    concept input_range =
      range<T> && input_iterator<iterator_t<T>>;
}

[editar] Concepto forward_range

namespace std::ranges {
  template<class T>
    concept forward_range =
      input_range<T> && forward_iterator<iterator_t<T>>;
}

[editar] Concepto bidirectional_range

namespace std::ranges {
  template<class T>
    concept bidirectional_range =
      forward_range<T> && bidirectional_iterator<iterator_t<T>>;
}

[editar] Concepto random_access_range

namespace std::ranges {
  template<class T>
    concept random_access_range =
      bidirectional_range<T> && random_access_iterator<iterator_t<T>>;
}

[editar] Concepto contiguous_range

namespace std::ranges {
  template<class T>
    concept contiguous_range =
      random_access_range<T> && contiguous_iterator<iterator_t<T>> &&
        requires(T& t) {
          { ranges::data(t) } -> same_as<add_pointer_t<range_reference_t<T>>>;
        };
}

[editar] Concepto common_range

namespace std::ranges {
  template<class T>
    concept common_range =
      range<T> && same_as<iterator_t<T>, sentinel_t<T>>;
}

[editar] Concepto viewable_range

namespace std::ranges {
  template<class T>
    concept viewable_range =
      range<T> && (borrowed_range<T> || view<remove_cvref_t<T>>);
}

[editar] Conceptos auxiliares

namespace std::ranges { // no especificado, solo para la búsqueda de nombre
  template<class R>
    concept __SimpleView =  // solo exposición
      view<R> && range<const R> &&
      same_as<iterator_t<R>, iterator_t<const R>> &&
      same_as<sentinel_t<R>, sentinel_t<const R>>;
 
  template<input_iterator I>
    concept __HasArrow =  // solo exposición
      is_pointer_v<I> || requires(I i) { i.operator->(); };
 
  template<class T, class U>
    concept __DifferentFrom =  // solo exposición
      !same_as<remove_cvref_t<T>, remove_cvref_t<U>>;
 
  template<class I>
    concept __Decrementable =  // solo exposición
      __Incrementable<I> && requires(I i) {
        { --i } -> same_as<I&>;
        { i-- } -> same_as<I>;
      };
 
  template<class I>
    concept __Advanceable =  // solo exposición
      __Decrementable<I> && totally_ordered<I> &&
      requires(I i, const I j, const iter_difference_t<I> n) {
          { i += n } -> same_as<I&>;
          { i -= n } -> same_as<I&>;
        I { j +  n };
        I { n +  j };
        I { j -  n };
          { j -  j } -> convertible_to<iter_difference_t<I>>;
      };
}

Nota: Estos nombres son solo para exposición, no forman parte de la interfaz.

[editar] Plantilla de clase std::ranges::view_interface

namespace std::ranges {
  template<class D>
    requires is_class_v<D> && same_as<D, remove_cv_t<D>>
  class view_interface : public view_base {
  private:
    constexpr D& derived() noexcept {  // solo exposición
      return static_cast<D&>(*this);
    }
    constexpr const D& derived() const noexcept {  // solo exposición
      return static_cast<const D&>(*this);
    }
  public:
    constexpr bool empty() requires forward_range<D> {
      return ranges::begin(derived()) == ranges::end(derived());
    }
    constexpr bool empty() const requires forward_range<const D> {
      return ranges::begin(derived()) == ranges::end(derived());
    }
 
    constexpr explicit operator bool()
      requires requires { ranges::empty(derived()); } {
        return !ranges::empty(derived());
      }
    constexpr explicit operator bool() const
      requires requires { ranges::empty(derived()); } {
        return !ranges::empty(derived());
      }
 
    constexpr auto data() requires contiguous_iterator<iterator_t<D>> {
      return to_address(ranges::begin(derived()));
    }
    constexpr auto data() const
      requires range<const D> && contiguous_iterator<iterator_t<const D>> {
        return to_address(ranges::begin(derived()));
      }
 
    constexpr auto size() requires forward_range<D> &&
      sized_sentinel_for<sentinel_t<D>, iterator_t<D>> {
        return ranges::end(derived()) - ranges::begin(derived());
      }
    constexpr auto size() const requires forward_range<const D> &&
      sized_sentinel_for<sentinel_t<const D>, iterator_t<const D>> {
        return ranges::end(derived()) - ranges::begin(derived());
      }
 
    constexpr decltype(auto) front() requires forward_range<D>;
    constexpr decltype(auto) front() const requires forward_range<const D>;
 
    constexpr decltype(auto) back() requires bidirectional_range<D> && common_range<D>;
    constexpr decltype(auto) back() const
      requires bidirectional_range<const D> && common_range<const D>;
 
    template<random_access_range R = D>
      constexpr decltype(auto) operator[](range_difference_t<R> n) {
        return ranges::begin(derived())[n];
      }
    template<random_access_range R = const D>
      constexpr decltype(auto) operator[](range_difference_t<R> n) const {
        return ranges::begin(derived())[n];
      }
  };
}

[editar] Plantilla de clase std::ranges::subrange

namespace std::ranges {
  template<class From, class To>
    concept __UsesNonqualificationPointerConversion =      // solo exposición
      is_pointer_v<From> && is_pointer_v<To> &&
      !convertible_to<remove_pointer_t<From>(*)[], remove_pointer_t<To>(*)[]>;
 
  template<class From, class To>
    concept __ConvertibleToNonSlicing =  // solo exposición
      convertible_to<From, To> &&
      !__UsesNonqualificationPointerConversion<decay_t<From>, decay_t<To>>;
 
  template<class T>
    concept __PairLike =  // solo exposición
      !is_reference_v<T> && requires(T t) {
        typename tuple_size<T>::type;  // se asegura de que tuple_size<T> esté completo
        requires derived_from<tuple_size<T>, integral_constant<size_t, 2>>;
        typename tuple_element_t<0, remove_const_t<T>>;
        typename tuple_element_t<1, remove_const_t<T>>;
        { get<0>(t) } -> convertible_to<const tuple_element_t<0, T>&>;
        { get<1>(t) } -> convertible_to<const tuple_element_t<1, T>&>;
      };
 
  template<class T, class U, class V>
    concept __PairLikeConvertibleFrom =  // solo exposición
      !range<T> && __PairLike<T> &&
      constructible_from<T, U, V> &&
      __ConvertibleToNonSlicing<U, tuple_element_t<0, T>> &&
      convertible_to<V, tuple_element_t<1, T>>;
 
  template<class T>
    concept __IteratorSentinelPair =  // solo exposición
      !range<T> && __PairLike<T> &&
      sentinel_for<tuple_element_t<1, T>, tuple_element_t<0, T>>;
 
  template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K =
      sized_sentinel_for<S, I> ? subrange_kind::sized : subrange_kind::unsized>
    requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
  class subrange : public view_interface<subrange<I, S, K>> {
  private:
    static constexpr bool StoreSize =                     // solo exposición
      K == subrange_kind::sized && !sized_sentinel_for<S, I>;
    I begin_ = I();                                       // solo exposición
    S end_ = S();                                         // solo exposición
    __MakeUnsignedLikeT<iter_difference_t<I>> size_ = 0;  // solo exposición; solo está presente
                                                          // cuando StoreSize es verdadero
  public:
    subrange() = default;
 
    constexpr subrange(__ConvertibleToNonSlicing<I> auto i, S s) requires (!StoreSize);
 
    constexpr subrange(__ConvertibleToNonSlicing<I> auto i, S s,
                       __MakeUnsignedLikeT<iter_difference_t<I>> n)
      requires (K == subrange_kind::sized);
 
    template<__DifferentFrom<subrange> R>
      requires borrowed_range<R> &&
               __ConvertibleToNonSlicing<iterator_t<R>, I> &&
               convertible_to<sentinel_t<R>, S>
    constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
 
    template<borrowed_range R>
      requires __ConvertibleToNonSlicing<iterator_t<R>, I> &&
               convertible_to<sentinel_t<R>, S>
    constexpr subrange(R&& r, __MakeUnsignedLikeT<iter_difference_t<I>> n)
      requires (K == subrange_kind::sized)
        : subrange{ranges::begin(r), ranges::end(r), n}
    {}
 
    template<__DifferentFrom<subrange> PairLike>
      requires __PairLikeConvertibleFrom<PairLike, const I&, const S&>
    constexpr operator PairLike() const;
 
    constexpr I begin() const requires copyable<I>;
    [[nodiscard]] constexpr I begin() requires (!copyable<I>);
    constexpr S end() const;
 
    constexpr bool empty() const;
    constexpr __MakeUnsignedLikeT<iter_difference_t<I>> size() const
      requires (K == subrange_kind::sized);
 
    [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const &
      requires forward_iterator<I>;
    [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) &&;
    [[nodiscard]] constexpr subrange prev(iter_difference_t<I> n = 1) const
      requires bidirectional_iterator<I>;
    constexpr subrange& advance(iter_difference_t<I> n);
  };
 
  template<input_or_output_iterator I, sentinel_for<I> S>
    subrange(I, S) -> subrange<I, S>;
 
  template<input_or_output_iterator I, sentinel_for<I> S>
    subrange(I, S, __MakeUnsignedLikeT<iter_difference_t<I>>) ->
      subrange<I, S, subrange_kind::sized>;
 
  template<__IteratorSentinelPair P>
    subrange(P) -> subrange<tuple_element_t<0, P>, tuple_element_t<1, P>>;
 
  template<__IteratorSentinelPair P>
    subrange(P, __MakeUnsignedLikeT<iter_difference_t<tuple_element_t<0, P>>>) ->
      subrange<tuple_element_t<0, P>, tuple_element_t<1, P>, subrange_kind::sized>;
 
  template<borrowed_range R>
    subrange(R&&) ->
      subrange<iterator_t<R>, sentinel_t<R>,
               (sized_range<R> || sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
                 ? subrange_kind::sized : subrange_kind::unsized>;
 
  template<borrowed_range R>
    subrange(R&&, __MakeUnsignedLikeT<range_difference_t<R>>) ->
      subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
 
  template<size_t N, class I, class S, subrange_kind K>
    requires (N < 2)
    constexpr auto get(const subrange<I, S, K>& r);
 
  template<size_t N, class I, class S, subrange_kind K>
    requires (N < 2)
    constexpr auto get(subrange<I, S, K>&& r);
}
 
namespace std {
  using ranges::get;
}

[editar] Clase std::ranges::dangling

namespace std::ranges {
  struct dangling {
    constexpr dangling() noexcept = default;
    template<class... Args>
      constexpr dangling(Args&&...) noexcept { }
  };
}

[editar] Plantilla de clase std::ranges::empty_view

namespace std::ranges {
  template<class T>
    requires is_object_v<T>
  class empty_view : public view_interface<empty_view<T>> {
  public:
    static constexpr T* begin() noexcept { return nullptr; }
    static constexpr T* end() noexcept { return nullptr; }
    static constexpr T* data() noexcept { return nullptr; }
    static constexpr size_t size() noexcept { return 0; }
    static constexpr bool empty() noexcept { return true; }
  };
}

[editar] Plantilla de clase std::ranges::single_view

namespace std::ranges {
  template<copy_constructible T>
    requires is_object_v<T>
  class single_view : public view_interface<single_view<T>> {
  private:
    __SemiregularBox<T> value_;  // solo exposición
  public:
    single_view() = default;
    constexpr explicit single_view(const T& t);
    constexpr explicit single_view(T&& t);
    template<class... Args>
      requires constructible_from<T, Args...>
    constexpr single_view(in_place_t, Args&&... args);
 
    constexpr T* begin() noexcept;
    constexpr const T* begin() const noexcept;
    constexpr T* end() noexcept;
    constexpr const T* end() const noexcept;
    static constexpr size_t size() noexcept;
    constexpr T* data() noexcept;
    constexpr const T* data() const noexcept;
  };
}

[editar] Plantilla de clase std::ranges::iota_view

namespace std::ranges {
  template<class I>
    concept __Decrementable =  // solo exposición
      /* véase definición */;
  template<class I>
    concept __Advanceable =  // solo exposición
      /* véase definición */;
 
  template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t>
    requires __WeaklyEqualityComparableWith<W, Bound> && semiregular<W>
  class iota_view : public view_interface<iota_view<W, Bound>> {
  private:
    // class iota_view::iterator
    struct iterator;         // solo exposición
    // class iota_view::sentinel
    struct sentinel;         // solo exposición
    W value_ = W();          // solo exposición
    Bound bound_ = Bound();  // solo exposición
  public:
    iota_view() = default;
    constexpr explicit iota_view(W value);
    constexpr iota_view(type_identity_t<W> value,
                        type_identity_t<Bound> bound);
    constexpr iota_view(iterator first, sentinel last) : iota_view(*first, last.bound_) {}
 
    constexpr iterator begin() const;
    constexpr auto end() const;
    constexpr iterator end() const requires same_as<W, Bound>;
 
    constexpr auto size() const requires /* véase definición */;
  };
 
  template<class W, class Bound>
    requires (!__IsIntegerLike<W> || !__IsIntegerLike<Bound> ||
              (__IsSignedIntegerLike<W> == __IsSignedIntegerLike<Bound>))
    iota_view(W, Bound) -> iota_view<W, Bound>;
}

[editar] Clase std::ranges::iota_view::iterator

namespace std::ranges {
  template<weakly_incrementable W, semiregular Bound>
    requires __WeaklyEqualityComparableWith<W, Bound>
  struct iota_view<W, Bound>::iterator {
  private:
    W value_ = W();  // solo exposición
  public:
    using iterator_concept = /* véase definición */;
    using iterator_category = input_iterator_tag;
    using value_type = W;
    using difference_type = /* __iota_difference_t<W> */;
 
    iterator() = default;
    constexpr explicit iterator(W value);
 
    constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);
 
    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int) requires __Incrementable<W>;
 
    constexpr iterator& operator--() requires __Decrementable<W>;
    constexpr iterator operator--(int) requires __Decrementable<W>;
 
    constexpr iterator& operator+=(difference_type n)
      requires __Advanceable<W>;
    constexpr iterator& operator-=(difference_type n)
      requires __Advanceable<W>;
    constexpr W operator[](difference_type n) const
      requires __Advanceable<W>;
 
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires equality_comparable<W>;
 
    friend constexpr bool operator<(const iterator& x, const iterator& y)
      requires totally_ordered<W>;
    friend constexpr bool operator>(const iterator& x, const iterator& y)
      requires totally_ordered<W>;
    friend constexpr bool operator<=(const iterator& x, const iterator& y)
      requires totally_ordered<W>;
    friend constexpr bool operator>=(const iterator& x, const iterator& y)
      requires totally_ordered<W>;
    friend constexpr auto operator<=>(const iterator& x, const iterator& y)
      requires totally_ordered<W> && three_way_comparable<W>;
 
    friend constexpr iterator operator+(iterator i, difference_type n)
      requires __Advanceable<W>;
    friend constexpr iterator operator+(difference_type n, iterator i)
      requires __Advanceable<W>;
 
    friend constexpr iterator operator-(iterator i, difference_type n)
      requires __Advanceable<W>;
    friend constexpr difference_type operator-(const iterator& x, const iterator& y)
      requires __Advanceable<W>;
  };
}

[editar] Clase std::ranges::iota_view::sentinel

namespace std::ranges {
  template<weakly_incrementable W, semiregular Bound>
    requires __WeaklyEqualityComparableWith<W, Bound>
  struct iota_view<W, Bound>::sentinel {
  private:
    Bound bound_ = Bound();  // solo exposición
  public:
    sentinel() = default;
    constexpr explicit sentinel(Bound bound);
 
    friend constexpr bool operator==(const iterator& x, const sentinel& y);
 
    friend constexpr iter_difference_t<W> operator-(const iterator& x, const sentinel& y)
      requires sized_sentinel_for<Bound, W>;
    friend constexpr iter_difference_t<W> operator-(const sentinel& x, const iterator& y)
      requires sized_sentinel_for<Bound, W>;
  };
}

[editar] Plantilla de clase std::ranges::basic_istream_view

namespace std::ranges {
  template<class Val, class CharT, class Traits>
    concept __StreamExtractable =  // solo exposición
      requires(basic_istream<CharT, Traits>& is, Val& t) {
         is >> t;
      };
 
  template<movable Val, class CharT, class Traits>
    requires default_initializable<Val> &&
             __StreamExtractable<Val, CharT, Traits>
  class basic_istream_view
        : public view_interface<basic_istream_view<Val, CharT, Traits>> {
  public:
    basic_istream_view() = default;
    constexpr explicit basic_istream_view(basic_istream<CharT, Traits>& stream);
 
    constexpr auto begin()
    {
      if (stream_) {
        *stream_ >> object_;
      }
      return iterator{*this};
    }
 
    constexpr default_sentinel_t end() const noexcept;
 
  private:
    struct iterator;                                  // solo exposición
    basic_istream<CharT, Traits>* stream_ = nullptr;  // solo exposición
    Val object_ = Val();                              // solo exposición
  };
}

[editar] Plantilla de clase std::ranges::basic_istream_view::iterator

namespace std::ranges {
  template<movable Val, class CharT, class Traits>
    requires default_initializable<Val> && __StreamExtractable<Val, CharT, Traits>
  class basic_istream_view<Val, CharT, Traits>::iterator {  // solo exposición
  public:
    using iterator_concept = input_iterator_tag;
    using difference_type = ptrdiff_t;
    using value_type = Val;
 
    iterator() = default;
    constexpr explicit iterator(basic_istream_view& parent) noexcept;
 
    iterator(const iterator&) = delete;
    iterator(iterator&&) = default;
 
    iterator& operator=(const iterator&) = delete;
    iterator& operator=(iterator&&) = default;
 
    iterator& operator++();
    void operator++(int);
 
    Val& operator*() const;
 
    friend bool operator==(const iterator& x, default_sentinel_t);
 
  private:
    basic_istream_view* parent_ = nullptr;  // solo exposición
  };
}

[editar] Plantilla de clase std::ranges::ref_view

namespace std::ranges {
  template<range R>
    requires is_object_v<R>
  class ref_view : public view_interface<ref_view<R>> {
  private:
    R* r_ = nullptr;  // solo exposición
  public:
    constexpr ref_view() noexcept = default;
 
    template<__DifferentFrom<ref_view> T>
      requires /* véase definición */
    constexpr ref_view(T&& t);
 
    constexpr R& base() const { return *r_; }
 
    constexpr iterator_t<R> begin() const { return ranges::begin(*r_); }
    constexpr sentinel_t<R> end() const { return ranges::end(*r_); }
 
    constexpr bool empty() const
      requires requires { ranges::empty(*r_); }
    { return ranges::empty(*r_); }
 
    constexpr auto size() const requires sized_range<R>
    { return ranges::size(*r_); }
 
    constexpr auto data() const requires contiguous_range<R>
    { return ranges::data(*r_); }
  };
  template<class R>
    ref_view(R&) -> ref_view<R>;
}

[editar] Plantilla de clase std::ranges::owning_view

namespace std::ranges {
template<range R>
    requires movable<R> && (!/*is-initializer-list*/<R>)
  class owning_view : public view_interface<owning_view<R>> {
  private:
    R r_ = R();   // solo exposición
  public:
    owning_view() requires default_initializable<R> = default;
    constexpr owning_view(R&& t);
 
    owning_view(owning_view&&) = default;
    owning_view& operator=(owning_view&&) = default;
 
    constexpr R& base() & { return r_; }
    constexpr const R& base() const& { return r_; }
    constexpr R&& base() && { return std::move(r_); }
    constexpr const R&& base() const&& { return std::move(r_); }
 
    constexpr iterator_t<R> begin() { return ranges::begin(r_); }
    constexpr sentinel_t<R> end() { return ranges::end(r_); }
 
    constexpr iterator_t<const R> begin() const requires range<const R>
    { return ranges::begin(r_); }
    constexpr sentinel_t<const R> end() const requires range<const R>
    { return ranges::end(r_); }
 
    constexpr bool empty()
      requires requires { ranges::empty(r_); }
    { return ranges::empty(r_); }
    constexpr bool empty() const
      requires requires { ranges::empty(r_); }
    { return ranges::empty(r_); }
 
    constexpr auto size() requires sized_range<R>
    { return ranges::size(r_); }
    constexpr auto size() const requires sized_range<const R>
    { return ranges::size(r_); }
 
    constexpr auto data() requires contiguous_range<R>
    { return ranges::data(r_); }
    constexpr auto data() const requires contiguous_range<const R>
    { return ranges::data(r_); }
  };
}

[editar] Plantilla de clase std::ranges::filter_view

namespace std::ranges {
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
    requires view<V> && is_object_v<Pred>
  class filter_view : public view_interface<filter_view<V, Pred>> {
  private:
    V base_ = V();                 // solo exposición
    __SemiregularBox<Pred> pred_;  // solo exposición
 
    // class filter_view::iterator
    class iterator;                // solo exposición
    // class filter_view::sentinel
    class sentinel;                // solo exposición
 
  public:
    filter_view() = default;
    constexpr filter_view(V base, Pred pred);
 
    constexpr V base() const& requires copy_constructible<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr const Pred& pred() const;
 
    constexpr iterator begin();
    constexpr auto end() {
      if constexpr (common_range<V>)
        return iterator{*this, ranges::end(base_)};
      else
        return sentinel{*this};
    }
  };
 
  template<class R, class Pred>
    filter_view(R&&, Pred) -> filter_view<views::all_t<R>, Pred>;
}

[editar] Clase std::ranges::filter_view::iterator

namespace std::ranges {
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
    requires view<V> && is_object_v<Pred>
  class filter_view<V, Pred>::iterator {
  private:
    iterator_t<V> current_ = iterator_t<V>();  // solo exposición
    filter_view* parent_ = nullptr;            // solo exposición
  public:
    using iterator_concept  = /* véase definición */;
    using iterator_category = /* véase definición */;
    using value_type        = range_value_t<V>;
    using difference_type   = range_difference_t<V>;
 
    iterator() = default;
    constexpr iterator(filter_view& parent, iterator_t<V> current);
 
    constexpr iterator_t<V> base() const &
      requires copyable<iterator_t<V>>;
    constexpr iterator_t<V> base() &&;
    constexpr range_reference_t<V> operator*() const;
    constexpr iterator_t<V> operator->() const
      requires __HasArrow<iterator_t<V>> && copyable<iterator_t<V>>;
 
    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int) requires forward_range<V>;
 
    constexpr iterator& operator--() requires bidirectional_range<V>;
    constexpr iterator operator--(int) requires bidirectional_range<V>;
 
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires equality_comparable<iterator_t<V>>;
 
    friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i)
      noexcept(noexcept(ranges::iter_move(i.current_)));
    friend constexpr void iter_swap(const iterator& x, const iterator& y)
      noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
      requires indirectly_swappable<iterator_t<V>>;
  };
}

[editar] Clase std::ranges::filter_view::sentinel

namespace std::ranges {
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
    requires view<V> && is_object_v<Pred>
  class filter_view<V, Pred>::sentinel {
  private:
    sentinel_t<V> end_ = sentinel_t<V>();  // solo exposición
  public:
    sentinel() = default;
    constexpr explicit sentinel(filter_view& parent);
 
    constexpr sentinel_t<V> base() const;
 
    friend constexpr bool operator==(const iterator& x, const sentinel& y);
  };
}

[editar] Plantilla de clase std::ranges::transform_view

namespace std::ranges {
  template<input_range V, copy_constructible F>
    requires view<V> && is_object_v<F> &&
             regular_invocable<F&, range_reference_t<V>> &&
             __CanReference<invoke_result_t<F&, range_reference_t<V>>>
  class transform_view : public view_interface<transform_view<V, F>> {
  private:
    // plantilla de clase transform_view::iterator
    template<bool> struct iterator;  // solo exposición
    // plantilla de clase transform_view::sentinel
    template<bool> struct sentinel;  // solo exposición
 
    V base_ = V();                   // solo exposición
    __SemiregularBox<F> fun_;        // solo exposición
 
  public:
    transform_view() = default;
    constexpr transform_view(V base, F fun);
 
    constexpr V base() const& requires copy_constructible<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr iterator<false> begin();
    constexpr iterator<true> begin() const
      requires range<const V> &&
               regular_invocable<const F&, range_reference_t<const V>>;
 
    constexpr sentinel<false> end();
    constexpr iterator<false> end() requires common_range<V>;
    constexpr sentinel<true> end() const
      requires range<const V> &&
               regular_invocable<const F&, range_reference_t<const V>>;
    constexpr iterator<true> end() const
      requires common_range<const V> &&
               regular_invocable<const F&, range_reference_t<const V>>;
 
    constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
    constexpr auto size() const requires sized_range<const V>
    { return ranges::size(base_); }
  };
 
  template<class R, class F>
    transform_view(R&&, F) -> transform_view<views::all_t<R>, F>;
}

[editar] Plantilla de clase std::ranges::transform_view::iterator

namespace std::ranges {
  template<input_range V, copy_constructible F>
    requires view<V> && is_object_v<F> &&
             regular_invocable<F&, range_reference_t<V>> &&
             __CanReference<invoke_result_t<F&, range_reference_t<V>>>
  template<bool Const>
  class transform_view<V, F>::iterator {
  private:
    using Parent =               // solo exposición
      conditional_t<Const, const transform_view, transform_view>;
    using Base   =               // solo exposición
      conditional_t<Const, const V, V>;
    iterator_t<Base> current_ =  // solo exposición
      iterator_t<Base>();
    Parent* parent_ = nullptr;   // solo exposición
  public:
    using iterator_concept  = /* véase definición */;
    using iterator_category = /* véase definición */;
    using value_type        =
      remove_cvref_t<invoke_result_t<F&, range_reference_t<Base>>>;
    using difference_type   = range_difference_t<Base>;
 
    iterator() = default;
    constexpr iterator(Parent& parent, iterator_t<Base> current);
    constexpr iterator(iterator<!Const> i)
      requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
 
    constexpr iterator_t<Base> base() const &
      requires copyable<iterator_t<Base>>;
    constexpr iterator_t<Base> base() &&;
    constexpr decltype(auto) operator*() const
    { return invoke(*parent_->fun_, *current_); }
 
    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int) requires forward_range<Base>;
 
    constexpr iterator& operator--() requires bidirectional_range<Base>;
    constexpr iterator operator--(int) requires bidirectional_range<Base>;
 
    constexpr iterator& operator+=(difference_type n)
      requires random_access_range<Base>;
    constexpr iterator& operator-=(difference_type n)
      requires random_access_range<Base>;
    constexpr decltype(auto) operator[](difference_type n) const
      requires random_access_range<Base>
    { return invoke(*parent_->fun_, current_[n]); }
 
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires equality_comparable<iterator_t<Base>>;
 
    friend constexpr bool operator<(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator<=(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>=(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr auto operator<=>(const iterator& x, const iterator& y)
      requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
 
    friend constexpr iterator operator+(iterator i, difference_type n)
      requires random_access_range<Base>;
    friend constexpr iterator operator+(difference_type n, iterator i)
      requires random_access_range<Base>;
 
    friend constexpr iterator operator-(iterator i, difference_type n)
      requires random_access_range<Base>;
    friend constexpr difference_type operator-(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
 
    friend constexpr decltype(auto) iter_move(const iterator& i)
      noexcept(noexcept(invoke(*i.parent_->fun_, *i.current_)))
    {
      if constexpr (is_lvalue_reference_v<decltype(*i)>)
        return std::move(*i);
      else
        return *i;
    }
}

[editar] Plantilla de clase std::ranges::transform_view::sentinel

namespace std::ranges {
  template<input_range V, copy_constructible F>
    requires view<V> && is_object_v<F> &&
             regular_invocable<F&, range_reference_t<V>> &&
             __CanReference<invoke_result_t<F&, range_reference_t<V>>>
  template<bool Const>
  class transform_view<V, F>::sentinel {
  private:
    using Parent =                                  // solo exposición
      conditional_t<Const, const transform_view, transform_view>;
    using Base = conditional_t<Const, const V, V>;  // solo exposición
    sentinel_t<Base> end_ = sentinel_t<Base>();     // solo exposición
  public:
    sentinel() = default;
    constexpr explicit sentinel(sentinel_t<Base> end);
    constexpr sentinel(sentinel<!Const> i)
      requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
 
    constexpr sentinel_t<Base> base() const;
 
    friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
    friend constexpr range_difference_t<Base>
      operator-(const iterator<Const>& x, const sentinel& y)
        requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
    friend constexpr range_difference_t<Base>
      operator-(const sentinel& y, const iterator<Const>& x)
        requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
  };
}

[editar] Plantilla de clase std::ranges::take_view

namespace std::ranges {
  template<view V>
  class take_view : public view_interface<take_view<V>> {
  private:
    V base_ = V();                     // solo exposición
    range_difference_t<V> count_ = 0;  // solo exposición
    // plantilla de clase take_view::sentinel
    template<bool> struct sentinel;    // solo exposición
  public:
    take_view() = default;
    constexpr take_view(V base, range_difference_t<V> count);
 
    constexpr V base() const& requires copy_constructible<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr auto begin() requires (!__SimpleView<V>) {
      if constexpr (sized_range<V>) {
        if constexpr (random_access_range<V>)
          return ranges::begin(base_);
        else {
          auto sz = size();
          return counted_iterator{ranges::begin(base_), sz};
        }
      } else
        return counted_iterator{ranges::begin(base_), count_};
    }
 
    constexpr auto begin() const requires range<const V> {
      if constexpr (sized_range<const V>) {
        if constexpr (random_access_range<const V>)
          return ranges::begin(base_);
        else {
          auto sz = size();
          return counted_iterator{ranges::begin(base_), sz};
        }
      } else
        return counted_iterator{ranges::begin(base_), count_};
    }
 
    constexpr auto end() requires (!__SimpleView<V>) {
      if constexpr (sized_range<V>) {
        if constexpr (random_access_range<V>)
          return ranges::begin(base_) + size();
        else
          return default_sentinel;
      } else
        return sentinel<false>{ranges::end(base_)};
    }
 
    constexpr auto end() const requires range<const V> {
      if constexpr (sized_range<const V>) {
        if constexpr (random_access_range<const V>)
          return ranges::begin(base_) + size();
        else
          return default_sentinel;
      } else
        return sentinel<true>{ranges::end(base_)};
    }
 
    constexpr auto size() requires sized_range<V> {
      auto n = ranges::size(base_);
      return ranges::min(n, static_cast<decltype(n)>(count_));
    }
 
    constexpr auto size() const requires sized_range<const V> {
      auto n = ranges::size(base_);
      return ranges::min(n, static_cast<decltype(n)>(count_));
    }
  };
 
  template<range R>
    take_view(R&&, range_difference_t<R>)
      -> take_view<views::all_t<R>>;
}

[editar] Plantilla de clase std::ranges::take_view::sentinel

namespace std::ranges {
  template<view V>
  template<bool Const>
  class take_view<V>::sentinel {
  private:
    using Base = conditional_t<Const, const V, V>;  // solo exposición
    using CI = counted_iterator<iterator_t<Base>>;  // solo exposición
    sentinel_t<Base> end_ = sentinel_t<Base>();     // solo exposición
  public:
    sentinel() = default;
    constexpr explicit sentinel(sentinel_t<Base> end);
    constexpr sentinel(sentinel<!Const> s)
      requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
 
    constexpr sentinel_t<Base> base() const;
 
    friend constexpr bool operator==(const CI& y, const sentinel& x);
  };
}

[editar] Plantilla de clase std::ranges::take_while_view

namespace std::ranges {
  template<view V, class Pred>
    requires input_range<V> && is_object_v<Pred> &&
             indirect_unary_predicate<const Pred, iterator_t<V>>
  class take_while_view : public view_interface<take_while_view<V, Pred>> {
    // plantilla de clase take_while_view::sentinel
    template<bool> class sentinel;  // solo exposición
 
    V base_ = V();                  // solo exposición
    __SemiregularBox<Pred> pred_;   // solo exposición
 
  public:
    take_while_view() = default;
    constexpr take_while_view(V base, Pred pred);
 
    constexpr V base() const& requires copy_constructible<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr const Pred& pred() const;
 
    constexpr auto begin() requires (!__SimpleView<V>)
    { return ranges::begin(base_); }
 
    constexpr auto begin() const requires range<const V>
    { return ranges::begin(base_); }
 
    constexpr auto end() requires (!__SimpleView<V>)
    { return sentinel<false>(ranges::end(base_), addressof(*pred_)); }
 
    constexpr auto end() const requires range<const V>
    { return sentinel<true>(ranges::end(base_), addressof(*pred_)); }
  };
 
  template<class R, class Pred>
    take_while_view(R&&, Pred) -> take_while_view<views::all_t<R>, Pred>;
}

[editar] Plantilla de clase std::ranges::take_while_view::sentinel

namespace std::ranges {
  template<view V, class Pred>
    requires input_range<V> && is_object_v<Pred> &&
             indirect_unary_predicate<const Pred, iterator_t<V>>
  template<bool Const>
  class take_while_view<V, Pred>::sentinel {        // solo exposición
    using Base = conditional_t<Const, const V, V>;  // solo exposición
 
    sentinel_t<Base> end_ = sentinel_t<Base>();     // solo exposición
    const Pred* pred_ = nullptr;                    // solo exposición
  public:
    sentinel() = default;
    constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
    constexpr sentinel(sentinel<!Const> s)
      requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
 
    constexpr sentinel_t<Base> base() const { return end_; }
 
    friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
  };
}

[editar] Plantilla de clase std::ranges::drop_view

namespace std::ranges {
  template<view V>
  class drop_view : public view_interface<drop_view<V>> {
  public:
    drop_view() = default;
    constexpr drop_view(V base, range_difference_t<V> count);
 
    constexpr V base() const& requires copy_constructible<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr auto begin()
      requires (!(__SimpleView<V> && random_access_range<V> && sized_range<const V>));
    constexpr auto begin() const
      requires random_access_range<const V> && sized_range<const V>;
 
    constexpr auto end()
      requires (!__SimpleView<V>)
    { return ranges::end(base_); }
 
    constexpr auto end() const
      requires range<const V>
    { return ranges::end(base_); }
 
    constexpr auto size()
      requires sized_range<V>
    {
      const auto s = ranges::size(base_);
      const auto c = static_cast<decltype(s)>(count_);
      return s < c ? 0 : s - c;
    }
 
    constexpr auto size() const
      requires sized_range<const V>
    {
      const auto s = ranges::size(base_);
      const auto c = static_cast<decltype(s)>(count_);
      return s < c ? 0 : s - c;
    }
  private:
    V base_ = V();                     // solo exposición
    range_difference_t<V> count_ = 0;  // solo exposición
  };
 
  template<class R>
    drop_view(R&&, range_difference_t<R>) -> drop_view<views::all_t<R>>;
}

[editar] Plantilla de clase std::ranges::drop_while_view

namespace std::ranges {
  template<view V, class Pred>
    requires input_range<V> && is_object_v<Pred> &&
             indirect_unary_predicate<const Pred, iterator_t<V>>
  class drop_while_view : public view_interface<drop_while_view<V, Pred>> {
  public:
    drop_while_view() = default;
    constexpr drop_while_view(V base, Pred pred);
 
    constexpr V base() const& requires copy_constructible<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr const Pred& pred() const;
 
    constexpr auto begin();
 
    constexpr auto end()
    { return ranges::end(base_); }
 
  private:
    V base_ = V();                 // solo exposición
    __SemiregularBox<Pred> pred_;  // solo exposición
  };
 
  template<class R, class Pred>
    drop_while_view(R&&, Pred) -> drop_while_view<views::all_t<R>, Pred>;
}

[editar] Plantilla de clase std::ranges::join_view

namespace std::ranges {
  template<input_range V>
    requires view<V> && input_range<range_reference_t<V>> &&
             (is_reference_v<range_reference_t<V>> ||
              view<range_value_t<V>>)
  class join_view : public view_interface<join_view<V>> {
  private:
    using InnerRng =                 // solo exposición
      range_reference_t<V>;
    // plantilla de clase join_view::iterator
    template<bool Const>
      struct iterator;               // solo exposición
    // plantilla de clase join_view::sentinel
    template<bool Const>
      struct sentinel;               // solo exposición
 
    V base_ = V();                   // solo exposición
    views::all_t<InnerRng> inner_ =  // solo exposición, solo está presente
      views::all_t<InnerRng>();      // cuando !is_reference_v<InnerRng>
  public:
    join_view() = default;
    constexpr explicit join_view(V base);
 
    constexpr V base() const& requires copy_constructible<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr auto begin() {
      constexpr bool use_const = __SimpleView<V> &&
                                 is_reference_v<range_reference_t<V>>;
      return iterator<use_const>{*this, ranges::begin(base_)};
    }
 
    constexpr auto begin() const
    requires input_range<const V> &&
             is_reference_v<range_reference_t<const V>> {
      return iterator<true>{*this, ranges::begin(base_)};
    }
 
    constexpr auto end() {
      if constexpr (forward_range<V> &&
                    is_reference_v<InnerRng> && forward_range<InnerRng> &&
                    common_range<V> && common_range<InnerRng>)
        return iterator<__SimpleView<V>>{*this, ranges::end(base_)};
      else
        return sentinel<__SimpleView<V>>{*this};
    }
 
    constexpr auto end() const
    requires input_range<const V> &&
             is_reference_v<range_reference_t<const V>> {
      if constexpr (forward_range<const V> &&
                    is_reference_v<range_reference_t<const V>> &&
                    forward_range<range_reference_t<const V>> &&
                    common_range<const V> &&
                    common_range<range_reference_t<const V>>)
        return iterator<true>{*this, ranges::end(base_)};
      else
        return sentinel<true>{*this};
    }
  };
 
  template<class R>
    explicit join_view(R&&) -> join_view<views::all_t<R>>;
}

[editar] Plantilla de clase std::ranges::join_view::iterator

namespace std::ranges {
  template<input_range V>
    requires view<V> && input_range<range_reference_t<V>> &&
             (is_reference_v<range_reference_t<V>> ||
              view<range_value_t<V>>)
  template<bool Const>
  struct join_view<V>::iterator {
  private:
    using Parent =                                       // solo exposición
      conditional_t<Const, const join_view, join_view>;
    using Base   = conditional_t<Const, const V, V>;     // solo exposición
 
    static constexpr bool __RefIsGlvalue =               // solo exposición
      is_reference_v<range_reference_t<Base>>;
 
    iterator_t<Base> outer_ = iterator_t<Base>();        // solo exposición
    iterator_t<range_reference_t<Base>> inner_ =         // solo exposición
      iterator_t<range_reference_t<Base>>();
    Parent* parent_ = nullptr;                           // solo exposición
 
    constexpr void satisfy();                            // solo exposición
  public:
    using iterator_concept  = /* véase definición */;
    using iterator_category = /* véase definición */;
    using value_type        = range_value_t<range_reference_t<Base>>;
    using difference_type   = /* véase definición */;
 
    iterator() = default;
    constexpr iterator(Parent& parent, iterator_t<Base> outer);
    constexpr iterator(iterator<!Const> i)
      requires Const &&
               convertible_to<iterator_t<V>, iterator_t<Base>> &&
               convertible_to<iterator_t<InnerRng>,
                              iterator_t<range_reference_t<Base>>>;
 
    constexpr decltype(auto) operator*() const { return *inner_; }
 
    constexpr iterator_t<Base> operator->() const
      requires __HasArrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
 
    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int)
      requires __RefIsGlvalue && forward_range<Base> &&
               forward_range<range_reference_t<Base>>;
 
    constexpr iterator& operator--()
      requires __RefIsGlvalue && bidirectional_range<Base> &&
               bidirectional_range<range_reference_t<Base>> &&
               common_range<range_reference_t<Base>>;
 
    constexpr iterator operator--(int)
      requires __RefIsGlvalue && bidirectional_range<Base> &&
               bidirectional_range<range_reference_t<Base>> &&
               common_range<range_reference_t<Base>>;
 
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires __RefIsGlvalue && equality_comparable<iterator_t<Base>> &&
               equality_comparable<iterator_t<range_reference_t<Base>>>;
 
    friend constexpr decltype(auto) iter_move(const iterator& i)
    noexcept(noexcept(ranges::iter_move(i.inner_))) {
      return ranges::iter_move(i.inner_);
    }
 
    friend constexpr void iter_swap(const iterator& x, const iterator& y)
      noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
  };
}

[editar] Plantilla de clase std::ranges::join_view::sentinel

namespace std::ranges {
  template<input_range V>
    requires view<V> && input_range<range_reference_t<V>> &&
             (is_reference_v<range_reference_t<V>> ||
              view<range_value_t<V>>)
  template<bool Const>
  struct join_view<V>::sentinel {
  private:
    using Parent =                                      // solo exposición
      conditional_t<Const, const join_view, join_view>;
    using Base   = conditional_t<Const, const V, V>;    // solo exposición
    sentinel_t<Base> end_ = sentinel_t<Base>();         // solo exposición
  public:
    sentinel() = default;
 
    constexpr explicit sentinel(Parent& parent);
    constexpr sentinel(sentinel<!Const> s)
      requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
 
    friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
  };
}

[editar] Plantilla de clase std::ranges::lazy_split_view

namespace std::ranges {
  template<auto> struct __RequireConstant;  // solo exposición
 
  template<class R>
  concept __TinyRange =  // solo exposición
    sized_range<R> &&
    requires { typename __RequireConstant<remove_reference_t<R>::size()>; } &&
    (remove_reference_t<R>::size() <= 1);
 
  template<input_range V, forward_range Pattern>
    requires view<V> && view<Pattern> &&
             indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (forward_range<V> || __TinyRange<Pattern>)
  class lazy_split_view : public view_interface<lazy_split_view<V, Pattern>> {
  private:
    V base_ = V();                             // solo exposición
    Pattern pattern_ = Pattern();              // solo exposición
 
    __NonPropagatingCache<iterator_t<V>> current_;       // solo exposición, solo está presente
                                                         // if !forward_range<V>
 
    // plantilla de clase lazy_split_view​::​__OuterIterator
    template<bool> struct __OuterIterator;     // solo exposición
 
    // plantilla de clase lazy_split_view​::​__InnerIterator
    template<bool> struct __InnerIterator;     // solo exposición
 
  public:
    lazy_split_view()
      requires default_initializable<V> && default_initializable<Pattern> = default;
    constexpr lazy_split_view(V base, Pattern pattern);
 
    template<input_range R>
      requires constructible_from<V, views::all_t<R>> &&
               constructible_from<Pattern, single_view<range_value_t<R>>>
    constexpr lazy_split_view(R&& r, range_value_t<R> e);
 
    constexpr V base() const& requires copy_constructible<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr auto begin() {
      if constexpr (forward_range<V>)
        return __OuterIterator<__SimpleView<V>>{*this, ranges::begin(base_)};
      else {
        current_ = ranges::begin(base_);
        return __OuterIterator<false>{*this};
      }
    }
 
    constexpr auto begin() const requires forward_range<V> && forward_range<const V> {
      return __OuterIterator<true>{*this, ranges::begin(base_)};
    }
 
    constexpr auto end() requires forward_range<V> && common_range<V> {
      return __OuterIterator<__SimpleView<V>>{*this, ranges::end(base_)};
    }
 
    constexpr auto end() const {
      if constexpr (forward_range<V> && forward_range<const V> && common_range<const V>)
        return __OuterIterator<true>{*this, ranges::end(base_)};
      else
        return default_sentinel;
    }
  };
 
  template<class R, class P>
    lazy_split_view(R&&, P&&) -> lazy_split_view<views::all_t<R>, views::all_t<P>>;
 
  template<input_range R>
    lazy_split_view(R&&, range_value_t<R>)
      -> lazy_split_view<views::all_t<R>, single_view<range_value_t<R>>>;
}

[editar] Plantilla de clase std::ranges::lazy_split_view::outer_iterator

namespace std::ranges {
  template<input_range V, forward_range Pattern>
    requires view<V> && view<Pattern> &&
             indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (forward_range<V> || __TinyRange<Pattern>)
  template<bool Const>
  struct lazy_split_view<V, Pattern>::__OuterIterator {
  private:
    using Parent = __MaybeConst<Const, lazy_split_view>;  // solo exposición
    using Base = __MaybeConst<Const, V>;                  // solo exposición
    Parent* parent_ = nullptr;                            // solo exposición
 
    iterator_t<Base> current_ = iterator_t<Base>();       // solo exposición, solo está presente
                                                          // si V modela forward_range
 
    bool trailing_empty_ = false;                         // solo exposición
 
  public:
    using iterator_concept  =
      conditional_t<forward_range<Base>, forward_iterator_tag, input_iterator_tag>;
 
    using iterator_category = input_iterator_tag;           // solo está presente si Base
                                                            // modela forward_range
 
    // class lazy_split_view​::​__OuterIterator​::​value_type
    struct value_type;
    using difference_type   = range_difference_t<Base>;
 
    __OuterIterator() = default;
    constexpr explicit __OuterIterator(Parent& parent)
      requires (!forward_range<Base>);
    constexpr __OuterIterator(Parent& parent, iterator_t<Base> current)
      requires forward_range<Base>;
    constexpr __OuterIterator(__OuterIterator<!Const> i)
      requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
 
    constexpr value_type operator*() const;
 
    constexpr __OuterIterator& operator++();
    constexpr decltype(auto) operator++(int) {
      if constexpr (forward_range<Base>) {
        auto tmp = *this;
        ++*this;
        return tmp;
      } else
        ++*this;
    }
 
    friend constexpr bool operator==(const __OuterIterator& x, const __OuterIterator& y)
      requires forward_range<Base>;
 
    friend constexpr bool operator==(const __OuterIterator& x, default_sentinel_t);
  };
}

[editar] Clase std::ranges::lazy_split_view::outer_iterator::value_type

namespace std::ranges {
  template<input_range V, forward_range Pattern>
    requires view<V> && view<Pattern> &&
             indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (forward_range<V> || __TinyRange<Pattern>)
  template<bool Const>
  struct lazy_split_view<V, Pattern>::__OuterIterator<Const>::value_type
    : view_interface<value_type> {
  private:
    __OuterIterator i_ = __OuterIterator();               // solo exposición
  public:
    value_type() = default;
    constexpr explicit value_type(__OuterIterator i);
 
    constexpr __InnerIterator<Const> begin() const;
    constexpr default_sentinel_t end() const;
  };
}

[editar] Plantilla de clase std::ranges::lazy_split_view::inner_iterator

namespace std::ranges {
  template<input_range V, forward_range Pattern>
    requires view<V> && view<Pattern> &&
             indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (forward_range<V> || __TinyRange<Pattern>)
  template<bool Const>
  struct lazy_split_view<V, Pattern>::__InnerIterator {
  private:
    using Base = __MaybeConst<Const, V>;                    // solo exposición
    __OuterIterator<Const> i_ = __OuterIterator<Const>();   // solo exposición
    bool incremented_ = false;                              // solo exposición
 
  public:
    using iterator_concept  = typename __OuterIterator<Const>::iterator_concept;
 
    using iterator_category = /*véase descripción*/;        // solo está presente si Base
                                                            // modela forward_range
    using value_type        = range_value_t<Base>;
    using difference_type   = range_difference_t<Base>;
 
    __InnerIterator() = default;
    constexpr explicit __InnerIterator(__OuterIterator<Const> i);
 
    constexpr const iterator_t<Base>& base() const &;
    constexpr iterator_t<Base> base() &&;
 
    constexpr decltype(auto) operator*() const { return *i_.current; }
 
    constexpr __InnerIterator& operator++();
    constexpr decltype(auto) operator++(int) {
      if constexpr (forward_range<Base>) {
        auto tmp = *this;
        ++*this;
        return tmp;
      } else
        ++*this;
    }
 
    friend constexpr bool operator==(const __InnerIterator& x, const __InnerIterator& y)
      requires forward_range<Base>;
 
    friend constexpr bool operator==(const __InnerIterator& x, default_sentinel_t);
 
    friend constexpr decltype(auto) iter_move(const __InnerIterator& i)
    noexcept(noexcept(ranges::iter_move(i.i_.current))) {
      return ranges::iter_move(i.i_.current);
    }
 
    friend constexpr void iter_swap(const __InnerIterator& x, const __InnerIterator& y)
      noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current)))
      requires indirectly_swappable<iterator_t<Base>>;
  };
}

[editar] Plantilla de clase std::ranges::split_view

namespace std::ranges {
  template<forward_range V, forward_range Pattern>
    requires view<V> && view<Pattern> &&
             indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
  class split_view : public view_interface<split_view<V, Pattern>> {
  private:
    V base_ = V();                              // solo exposición
    Pattern pattern_ = Pattern();               // solo exposición
    // class split_view​::​iterator
    struct iterator;                            // solo exposición
    // class split_view​::​sentinel
    struct sentinel;                            // solo exposición
 
  public:
    split_view()
      requires default_initializable<V> && default_initializable<Pattern> = default;
    constexpr split_view(V base, Pattern pattern);
 
    template<forward_range R>
      requires constructible_from<V, views::all_t<R>> &&
               constructible_from<Pattern, single_view<range_value_t<R>>>
    constexpr split_view(R&& r, range_value_t<R> e);
 
    constexpr V base() const& requires copyable<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr iterator begin();
 
    constexpr auto end() {
      if constexpr (common_range<V>) {
        return iterator{*this, ranges::end(base_), {} };
      } else {
        return sentinel{*this};
      }
    }
 
    constexpr subrange<iterator_t<V>> __FindNext(iterator_t<V>); // solo exposición
  };
 
  template<class R, class P>
    split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>;
 
  template<forward_range R>
    split_view(R&&, range_value_t<R>)
      -> split_view<views::all_t<R>, single_view<range_value_t<R>>>;
}

[editar] Plantilla de clase std::ranges::split_view​::​iterator

namespace std::ranges {
  template<forward_range V, forward_range Pattern>
    requires view<V> && view<Pattern> &&
             indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
  class split_view<V, Pattern>::iterator {
  private:
    split_view* parent_ = nullptr;                              // solo exposición
    iterator_t<V> cur_ = iterator_t<V>();                       // solo exposición
    subrange<iterator_t<V>> next_ = subrange<iterator_t<V>>();  // solo exposición
    bool trailing_empty_ = false;                               // solo exposición
 
  public:
    using iterator_concept = forward_iterator_tag;
    using iterator_category = input_iterator_tag;
    using value_type = subrange<iterator_t<V>>;
    using difference_type = range_difference_t<V>;
 
    iterator() = default;
    constexpr iterator(split_view& parent, iterator_t<V> current,
                       subrange<iterator_t<V>> next);
 
    constexpr iterator_t<V> base() const;
    constexpr value_type operator*() const;
 
    constexpr iterator& operator++();
    constexpr iterator operator++(int);
 
    friend constexpr bool operator==(const iterator& x, const iterator& y);
  };
}

[editar] Plantilla de clase std::ranges::split_view​::​sentinel

namespace std::ranges {
  template<forward_range V, forward_range Pattern>
    requires view<V> && view<Pattern> &&
             indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
  struct split_view<V, Pattern>::sentinel {
  private:
    sentinel_t<V> end_ = sentinel_t<V>();               // solo exposición
 
  public:
    sentinel() = default;
    constexpr explicit sentinel(split_view& parent);
 
    friend constexpr bool operator==(const iterator& x, const sentinel& y);
  };
}

[editar] Plantilla de clase std::ranges::common_view

namespace std::ranges {
  template<view V>
    requires (!common_range<V> && copyable<iterator_t<V>>)
  class common_view : public view_interface<common_view<V>> {
  private:
    V base_ = V();  // solo exposición
  public:
    common_view() = default;
 
    constexpr explicit common_view(V r);
 
    template<viewable_range R>
      requires (!common_range<R> && constructible_from<V, views::all_t<R>>)
    constexpr explicit common_view(R&& r);
 
    constexpr V base() const& requires copy_constructible<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr auto begin() {
      if constexpr (random_access_range<V> && sized_range<V>)
        return ranges::begin(base_);
      else
        return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::begin(base_));
    }
 
    constexpr auto begin() const requires range<const V> {
      if constexpr (random_access_range<const V> && sized_range<const V>)
        return ranges::begin(base_);
      else
        return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_));
    }
 
    constexpr auto end() {
      if constexpr (random_access_range<V> && sized_range<V>)
        return ranges::begin(base_) + ranges::size(base_);
      else
        return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_));
    }
 
    constexpr auto end() const requires range<const V> {
      if constexpr (random_access_range<const V> && sized_range<const V>)
        return ranges::begin(base_) + ranges::size(base_);
      else
        return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(base_));
    }
 
    constexpr auto size() requires sized_range<V> {
      return ranges::size(base_);
    }
    constexpr auto size() const requires sized_range<const V> {
      return ranges::size(base_);
    }
  };
 
  template<class R>
    common_view(R&&) -> common_view<views::all_t<R>>;
}

[editar] Plantilla de clase std::ranges::reverse_view

namespace std::ranges {
  template<view V>
    requires bidirectional_range<V>
  class reverse_view : public view_interface<reverse_view<V>> {
  private:
    V base_ = V();  // solo exposición
  public:
    reverse_view() = default;
 
    constexpr explicit reverse_view(V r);
 
    constexpr V base() const& requires copy_constructible<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr reverse_iterator<iterator_t<V>> begin();
    constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>;
    constexpr auto begin() const requires common_range<const V>;
 
    constexpr reverse_iterator<iterator_t<V>> end();
    constexpr auto end() const requires common_range<const V>;
 
    constexpr auto size() requires sized_range<V> {
      return ranges::size(base_);
    }
    constexpr auto size() const requires sized_range<const V> {
      return ranges::size(base_);
    }
  };
 
  template<class R>
    reverse_view(R&&) -> reverse_view<views::all_t<R>>;
}

[editar] Plantilla de clase std::ranges::elements_view

namespace std::ranges {
  template<class T, size_t N>
  concept __HasTupleElement =  // solo exposición
    requires(T t) {
      typename tuple_size<T>::type;
      requires N < tuple_size_v<T>;
      typename tuple_element_t<N, T>;
      { get<N>(t) } -> convertible_to<const tuple_element_t<N, T>&>;
    };
 
  template<input_range V, size_t N>
    requires view<V> && __HasTupleElement<range_value_t<V>, N> &&
             __HasTupleElement<remove_reference_t<range_reference_t<V>>, N>
  class elements_view : public view_interface<elements_view<V, N>> {
  public:
    elements_view() = default;
    constexpr explicit elements_view(V base);
 
    constexpr V base() const& requires copy_constructible<V> { return base_; }
    constexpr V base() && { return std::move(base_); }
 
    constexpr auto begin() requires (!__SimpleView<V>)
    { return iterator<false>(ranges::begin(base_)); }
 
    constexpr auto begin() const requires __SimpleView<V>
    { return iterator<true>(ranges::begin(base_)); }
 
    constexpr auto end()
    { return sentinel<false>{ranges::end(base_)}; }
 
    constexpr auto end() requires common_range<V>
    { return iterator<false>{ranges::end(base_)}; }
 
    constexpr auto end() const requires range<const V>
    { return sentinel<true>{ranges::end(base_)}; }
 
    constexpr auto end() const requires common_range<const V>
    { return iterator<true>{ranges::end(base_)}; }
 
    constexpr auto size() requires sized_range<V>
    { return ranges::size(base_); }
 
    constexpr auto size() const requires sized_range<const V>
    { return ranges::size(base_); }
 
  private:
    // plantilla de clase elements_view::iterator
    template<bool> struct iterator;  // solo exposición
    // plantilla de clase elements_view::sentinel
    template<bool> struct sentinel;  // solo exposición
    V base_ = V();                   // solo exposición
  };
}

[editar] Plantilla de clase std::ranges::elements_view::iterator

namespace std::ranges {
  template<input_range V, size_t N>
    requires view<V> && __HasTupleElement<range_value_t<V>, N> &&
             __HasTupleElement<remove_reference_t<range_reference_t<V>>, N>
  template<bool Const>
  class elements_view<V, N>::iterator {             // solo exposición
    using Base = conditional_t<Const, const V, V>;  // solo exposición
 
    iterator_t<Base> current_ = iterator_t<Base>();
  public:
    using iterator_category = typename iterator_traits<iterator_t<Base>>::iterator_category;
    using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<Base>>>;
    using difference_type = range_difference_t<Base>;
 
    iterator() = default;
    constexpr explicit iterator(iterator_t<Base> current);
    constexpr iterator(iterator<!Const> i)
      requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
 
    constexpr iterator_t<Base> base() const&
      requires copyable<iterator_t<Base>>;
    constexpr iterator_t<Base> base() &&;
 
    constexpr decltype(auto) operator*() const
    { return get<N>(*current_); }
 
    constexpr iterator& operator++();
    constexpr void operator++(int) requires (!forward_range<Base>);
    constexpr iterator operator++(int) requires forward_range<Base>;
 
    constexpr iterator& operator--() requires bidirectional_range<Base>;
    constexpr iterator operator--(int) requires bidirectional_range<Base>;
 
    constexpr iterator& operator+=(difference_type x)
      requires random_access_range<Base>;
    constexpr iterator& operator-=(difference_type x)
      requires random_access_range<Base>;
 
    constexpr decltype(auto) operator[](difference_type n) const
      requires random_access_range<Base>
    { return get<N>(*(current_ + n)); }
 
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires equality_comparable<iterator_t<Base>>;
 
    friend constexpr bool operator<(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator<=(const iterator& y, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>=(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr auto operator<=>(const iterator& x, const iterator& y)
      requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
 
    friend constexpr iterator operator+(const iterator& x, difference_type y)
      requires random_access_range<Base>;
    friend constexpr iterator operator+(difference_type x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr iterator operator-(const iterator& x, difference_type y)
      requires random_access_range<Base>;
    friend constexpr difference_type operator-(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
  };
}

[editar] Plantilla de clase std::ranges::elements_view::sentinel

namespace std::ranges {
  template<input_range V, size_t N>
    requires view<V> && __HasTupleElement<range_value_t<V>, N> &&
             __HasTupleElement<remove_reference_t<range_reference_t<V>>, N>
  template<bool Const>
  class elements_view<V, N>::sentinel {             // solo exposición
  private:
    using Base = conditional_t<Const, const V, V>;  // solo exposición
    sentinel_t<Base> end_ = sentinel_t<Base>();     // solo exposición
  public:
    sentinel() = default;
    constexpr explicit sentinel(sentinel_t<Base> end);
    constexpr sentinel(sentinel<!Const> other)
      requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
 
    constexpr sentinel_t<Base> base() const;
 
    friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
    friend constexpr range_difference_t<Base>
      operator-(const iterator<Const>& x, const sentinel& y)
        requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
    friend constexpr range_difference_t<Base>
      operator-(const sentinel& x, const iterator<Const>& y)
        requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
  };
}

[editar] Plantilla de clase std::ranges::zip_view

namespace std::ranges {
  template<class... Rs>
  concept __ZipIsCommon =                             // solo exposición
    (sizeof...(Rs) == 1 && (common_range<Rs> && ...)) ||
    (!(bidirectional_range<Rs> && ...) && (common_range<Rs> && ...)) ||
    ((random_access_range<Rs> && ...) && (sized_range<Rs> && ...));
 
  template<class... Ts>
    using TupleOrPair = /* véase a continuación */;   // solo exposición
 
  template<class F, class Tuple>
  constexpr auto __TupleTransform(F&& f, Tuple&& tuple) { // solo exposición
    return apply([&]<class... Ts>(Ts&&... elements) {
      return TupleOrPair<invoke_result_t<F&, Ts>...>(
        invoke(f, std::forward<Ts>(elements))...
      );
    }, std::forward<Tuple>(tuple));
  }
 
  template<class F, class Tuple>
  constexpr void TupleForEach(F&& f, Tuple&& tuple) { // solo exposición
    apply([&]<class... Ts>(Ts&&... elements) {
      (invoke(f, std::forward<Ts>(elements)), ...);
    }, std::forward<Tuple>(tuple));
  }
 
  template<input_range... Views>
    requires (view<Views> && ...) && (sizeof...(Views) > 0)
  class zip_view : public view_interface<zip_view<Views...>> {
    tuple<Views...> views_;             // solo exposición
 
    // plantilla de clase zip_view​::​iterator
    template<bool> class iterator;      // solo exposición
 
    // plantilla de clase zip_view​::​sentinel
    template<bool> class sentinel;      // solo exposición
 
  public:
    zip_view() = default;
    constexpr explicit zip_view(Views... views);
 
    constexpr auto begin() requires (!(__SimpleView<Views> && ...)) {
      return iterator<false>(__TupleTransform(ranges::begin, views_));
    }
    constexpr auto begin() const requires (range<const Views> && ...) {
      return iterator<true>(__TupleTransform(ranges::begin, views_));
    }
 
    constexpr auto end() requires (!(__SimpleView<Views> && ...)) {
      if constexpr (!__ZipIsCommon<Views...>) {
        return sentinel<false>(__TupleTransform(ranges::end, views_));
      } else if constexpr ((random_access_range<Views> && ...)) {
        return begin() + iter_difference_t<iterator<false>>(size());
      } else {
        return iterator<false>(__TupleTransform(ranges::end, views_));
      }
    }
 
    constexpr auto end() const requires (range<const Views> && ...) {
      if constexpr (!__ZipIsCommon<const Views...>) {
        return sentinel<true>(__TupleTransform(ranges::end, views_));
      } else if constexpr ((random_access_range<const Views> && ...)) {
        return begin() + iter_difference_t<iterator<true>>(size());
      } else {
        return iterator<true>(__TupleTransform(ranges::end, views_));
      }
    }
 
    constexpr auto size() requires (sized_range<Views> && ...);
    constexpr auto size() const requires (sized_range<const Views> && ...);
  };
 
  template<class... Rs>
    zip_view(Rs&&...) -> zip_view<views::all_t<Rs>...>;
}

[editar] Plantilla de clase std::ranges::zip_view::iterator

namespace std::ranges {
  template<bool Const, class... Views>
    concept __AllRandomAccess =                  // solo exposición
      (random_access_range<__MaybeConst<Const, Views>> && ...);
  template<bool Const, class... Views>
    concept __AllBidirectional =                 // solo exposición
      (bidirectional_range<__MaybeConst<Const, Views>> && ...);
  template<bool Const, class... Views>
    concept __AllForward =                       // solo exposición
      (forward_range<__MaybeConst<Const, Views>> && ...);
 
  template<input_range... Views>
    requires (view<Views> && ...) && (sizeof...(Views) > 0)
  template<bool Const>
  class zip_view<Views...>::iterator {
    TupleOrPair<iterator_t<__MaybeConst<Const, Views>>...> current_;       // solo exposición
    constexpr explicit iterator(TupleOrPair<iterator_t<__MaybeConst<Const, Views>>...>);
                                                                           // solo exposición
  public:
    using iterator_category = input_iterator_tag;                          // no siempre está presente
    using iterator_concept  = /* véase a continuación */;
    using value_type = TupleOrPair<range_value_t<__MaybeConst<Const, Views>>...>;
    using difference_type = common_type_t<range_difference_t<__MaybeConst<Const, Views>>...>;
 
    iterator() = default;
    constexpr iterator(iterator<!Const> i)
      requires Const && (convertible_to<iterator_t<Views>,
                                        iterator_t<__MaybeConst<Const, Views>>> && ...);
 
    constexpr auto operator*() const;
    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int) requires __AllForward<Const, Views...>;
 
    constexpr iterator& operator--() requires __AllBidirectional<Const, Views...>;
    constexpr iterator operator--(int) requires __AllBidirectional<Const, Views...>;
 
    constexpr iterator& operator+=(difference_type x)
      requires __AllRandomAccess<Const, Views...>;
    constexpr iterator& operator-=(difference_type x)
      requires __AllRandomAccess<Const, Views...>;
 
    constexpr auto operator[](difference_type n) const
      requires __AllRandomAccess<Const, Views...>;
 
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires (equality_comparable<iterator_t<__MaybeConst<Const, Views>>> && ...);
 
    friend constexpr bool operator<(const iterator& x, const iterator& y)
      requires __AllRandomAccess<Const, Views...>;
    friend constexpr bool operator>(const iterator& x, const iterator& y)
      requires __AllRandomAccess<Const, Views...>;
    friend constexpr bool operator<=(const iterator& x, const iterator& y)
      requires __AllRandomAccess<Const, Views...>;
    friend constexpr bool operator>=(const iterator& x, const iterator& y)
      requires __AllRandomAccess<Const, Views...>;
    friend constexpr auto operator<=>(const iterator& x, const iterator& y)
      requires __AllRandomAccess<Const, Views...> &&
               (three_way_comparable<iterator_t<__MaybeConst<Const, Views>>> && ...);
 
    friend constexpr iterator operator+(const iterator& i, difference_type n)
      requires __AllRandomAccess<Const, Views...>;
    friend constexpr iterator operator+(difference_type n, const iterator& i)
      requires __AllRandomAccess<Const, Views...>;
    friend constexpr iterator operator-(const iterator& i, difference_type n)
      requires __AllRandomAccess<Const, Views...>;
    friend constexpr difference_type operator-(const iterator& x, const iterator& y)
      requires (sized_sentinel_for<iterator_t<__MaybeConst<Const, Views>>,
                                   iterator_t<__MaybeConst<Const, Views>>> && ...);
 
    friend constexpr auto iter_move(const iterator& i)
      noexcept(/* véase a continuación */);
 
    friend constexpr void iter_swap(const iterator& l, const iterator& r)
      noexcept(/* véase a continuación */)
      requires (indirectly_swappable<iterator_t<__MaybeConst<Const, Views>>> && ...);
  };
}

[editar] Plantilla de clase std::ranges::zip_view::sentinel

namespace std::ranges {
  template<input_range... Views>
    requires (view<Views> && ...) && (sizeof...(Views) > 0)
  template<bool Const>
  class zip_view<Views...>::sentinel {
    TupleOrPair<sentinel_t<__MaybeConst<Const, Views>>...> end_;    // solo exposición
    constexpr explicit sentinel(TupleOrPair<sentinel_t<__MaybeConst<Const, Views>>...> end);
                                                                    // solo exposición
  public:
    sentinel() = default;
    constexpr sentinel(sentinel<!Const> i)
      requires Const &&
               (convertible_to<sentinel_t<Views>,
                sentinel_t<__MaybeConst<Const, Views>>> && ...);
 
    template<bool OtherConst>
      requires (sentinel_for<sentinel_t<__MaybeConst<Const, Views>>,
                             iterator_t<__MaybeConst<OtherConst, Views>>> && ...)
    friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
 
    template<bool OtherConst>
      requires (sized_sentinel_for<sentinel_t<__MaybeConst<Const, Views>>,
                                   iterator_t<__MaybeConst<OtherConst, Views>>> && ...)
    friend constexpr common_type_t<range_difference_t<__MaybeConst<OtherConst, Views>>...>
      operator-(const iterator<OtherConst>& x, const sentinel& y);
 
    template<bool OtherConst>
      requires (sized_sentinel_for<sentinel_t<__MaybeConst<Const, Views>>,
                                   iterator_t<__MaybeConst<OtherConst, Views>>> && ...)
    friend constexpr common_type_t<range_difference_t<__MaybeConst<OtherConst, Views>>...>
      operator-(const sentinel& y, const iterator<OtherConst>& x);
  };
}

[editar] Plantilla de clase std::ranges::zip_transform_view

namespace std::ranges {
  template<copy_constructible F, input_range... Views>
    requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
              regular_invocable<F&, range_reference_t<Views>...> &&
              __CanReference<invoke_result_t<F&, range_reference_t<Views>...>>
  class zip_transform_view : public view_interface<zip_transform_view<F, Views...>> {
    __CopyableBox<F> fun_;                  // solo exposición
    zip_view<Views...> zip_;                // solo exposición
 
    using InnerView = zip_view<Views...>;   // solo exposición
    template<bool Const>
      using ziperator = iterator_t<__MaybeConst<Const, InnerView>>;      // solo exposición
    template<bool Const>
      using zentinel = sentinel_t<__MaybeConst<Const, InnerView>>;       // solo exposición
 
    // plantilla de clase zip_transform_view​::​iterator
    template<bool> class iterator;          // solo exposición
 
    // plantilla de clase zip_transform_view​::​sentinel
    template<bool> class sentinel;          // solo exposición
 
  public:
    zip_transform_view() = default;
 
    constexpr explicit zip_transform_view(F fun, Views... views);
 
    constexpr auto begin() { return iterator<false>(*this, zip_.begin()); }
 
    constexpr auto begin() const
      requires range<const InnerView> &&
               regular_invocable<const F&, range_reference_t<const Views>...> {
      return iterator<true>(*this, zip_.begin());
    }
 
    constexpr auto end() {
      if constexpr (common_range<InnerView>) {
        return iterator<false>(*this, zip_.end());
      } else {
        return sentinel<false>(zip_.end());
      }
    }
 
    constexpr auto end() const
      requires range<const InnerView> &&
               regular_invocable<const F&, range_reference_t<const Views>...> {
      if constexpr (common_range<const InnerView>) {
        return iterator<true>(*this, zip_.end());
      } else {
        return sentinel<true>(zip_.end());
      }
    }
 
    constexpr auto size() requires sized_range<InnerView> {
      return zip_.size();
    }
 
    constexpr auto size() const requires sized_range<const InnerView> {
      return zip_.size();
    }
  };
 
  template<class F, class... Rs>
    zip_transform_view(F, Rs&&...) -> zip_transform_view<F, views::all_t<Rs>...>;
}

[editar] Plantilla de clase std::ranges::zip_transform_view::iterator

namespace std::ranges {
  template<copy_constructible F, input_range... Views>
    requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
              regular_invocable<F&, range_reference_t<Views>...> &&
              __CanReference<invoke_result_t<F&, range_reference_t<Views>...>>
  template<bool Const>
  class zip_transform_view<F, Views...>::iterator {
    using Parent = __MaybeConst<Const, zip_transform_view>;      // solo exposición
    using Base = __MaybeConst<Const, InnerView>;                 // solo exposición
    Parent* parent_ = nullptr;                                   // solo exposición
    ziperator<Const> inner_;                                     // solo exposición
 
    constexpr iterator(Parent& parent, ziperator<Const> inner);  // solo exposición
 
  public:
    using iterator_category = /* véase a continuación */;        // no siempre está presente
    using iterator_concept  = typename ziperator<Const>::iterator_concept;
    using value_type =
      remove_cvref_t<invoke_result_t<__MaybeConst<Const, F>&,
                                     range_reference_t<__MaybeConst<Const, Views>>...>>;
    using difference_type = range_difference_t<Base>;
 
    iterator() = default;
    constexpr iterator(iterator<!Const> i)
      requires Const && convertible_to<ziperator<false>, ziperator<Const>>;
 
    constexpr decltype(auto) operator*() const noexcept(/* véase a continuación */);
    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int) requires forward_range<Base>;
 
    constexpr iterator& operator--() requires bidirectional_range<Base>;
    constexpr iterator operator--(int) requires bidirectional_range<Base>;
 
    constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
    constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
 
    constexpr decltype(auto) operator[](difference_type n) const
      requires random_access_range<Base>;
 
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires equality_comparable<ziperator<Const>>;
 
    friend constexpr bool operator<(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator<=(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>=(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr auto operator<=>(const iterator& x, const iterator& y)
      requires random_access_range<Base> && three_way_comparable<ziperator<Const>>;
 
    friend constexpr iterator operator+(const iterator& i, difference_type n)
      requires random_access_range<Base>;
    friend constexpr iterator operator+(difference_type n, const iterator& i)
      requires random_access_range<Base>;
    friend constexpr iterator operator-(const iterator& i, difference_type n)
      requires random_access_range<Base>;
    friend constexpr difference_type operator-(const iterator& x, const iterator& y)
      requires sized_sentinel_for<ziperator<Const>, ziperator<Const>>;
  };
}

[editar] Plantilla de clase std::ranges::zip_transform_view::sentinel

namespace std::ranges {
  template<copy_constructible F, input_range... Views>
    requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
              regular_invocable<F&, range_reference_t<Views>...> &&
              __CanReference<invoke_result_t<F&, range_reference_t<Views>...>>
  template<bool Const>
  class zip_transform_view<F, Views...>::sentinel {
    zentinel<Const> inner_;                                     // solo exposición
    constexpr explicit sentinel(zentinel<Const> inner);         // solo exposición
 
  public:
    sentinel() = default;
    constexpr sentinel(sentinel<!Const> i)
      requires Const && convertible_to<zentinel<false>, zentinel<Const>>;
 
    template<bool OtherConst>
      requires sentinel_for<zentinel<Const>, ziperator<OtherConst>>
    friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
 
    template<bool OtherConst>
      requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>
    friend constexpr range_difference_t<__MaybeConst<OtherConst, InnerView>>
      operator-(const iterator<OtherConst>& x, const sentinel& y);
 
    template<bool OtherConst>
      requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>
    friend constexpr range_difference_t<__MaybeConst<OtherConst, InnerView>>
      operator-(const sentinel& x, const iterator<OtherConst>& y);
  };
}

[editar] Plantilla de clase std::ranges::adjacent_view

namespace std::ranges {
  template<forward_range V, size_t N>
    requires view<V> && (N > 0)
  class adjacent_view : public view_interface<adjacent_view<V, N>> {
    V base_ = V();                      // solo exposición
 
    // plantilla de clase adjacent_view​::​iterator
    template<bool> class iterator;      // solo exposición
 
    // plantilla de clase adjacent_view​::​sentinel
    template<bool> class sentinel;      // solo exposición
 
    struct AsSentinel{};               // solo exposición
 
  public:
    adjacent_view() requires default_initializable<V> = default;
    constexpr explicit adjacent_view(V base);
 
    constexpr auto begin() requires (!__SimpleView<V>) {
      return iterator<false>(ranges::begin(base_), ranges::end(base_));
    }
 
    constexpr auto begin() const requires range<const V> {
      return iterator<true>(ranges::begin(base_), ranges::end(base_));
    }
 
    constexpr auto end() requires (!__SimpleView<V>) {
      if constexpr (common_range<V>) {
        return iterator<false>(AsSentinel{}, ranges::begin(base_), ranges::end(base_));
      } else {
        return sentinel<false>(ranges::end(base_));
      }
    }
 
    constexpr auto end() const requires range<const V> {
      if constexpr (common_range<const V>) {
        return iterator<true>(AsSentinel{}, ranges::begin(base_), ranges::end(base_));
      } else {
        return sentinel<true>(ranges::end(base_));
      }
    }
 
    constexpr auto size() requires sized_range<V>;
    constexpr auto size() const requires sized_range<const V>;
  };
}

[editar] Plantilla de clase std::ranges::adjacent_view::iterator

namespace std::ranges {
  template<forward_range V, size_t N>
    requires view<V> && (N > 0)
  template<bool Const>
  class adjacent_view<V, N>::iterator {
    using Base = __MaybeConst<Const, V>;                                 // solo exposición
    array<iterator_t<Base>, N> current_ = array<iterator_t<Base>, N>();  // solo exposición
    constexpr iterator(iterator_t<Base> first, sentinel_t<Base> last);   // solo exposición
    constexpr iterator(AsSentinel, iterator_t<Base> first, iterator_t<Base> last);
                                                                         // solo exposición
  public:
    using iterator_category = input_iterator_tag;
    using iterator_concept  = /* véase a continuación */;
    // sea REPEAT(T, N) como un paquete de N tipos, donde cada uno denota el mismo tipo que T
    using value_type = TupleOrPair</* REPEAT(range_value_t<Base>, N) */...>;
    using difference_type = range_difference_t<Base>;
 
    iterator() = default;
    constexpr iterator(iterator<!Const> i)
      requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
 
    constexpr auto operator*() const;
    constexpr iterator& operator++();
    constexpr iterator operator++(int);
 
    constexpr iterator& operator--() requires bidirectional_range<Base>;
    constexpr iterator operator--(int) requires bidirectional_range<Base>;
 
    constexpr iterator& operator+=(difference_type x)
      requires random_access_range<Base>;
    constexpr iterator& operator-=(difference_type x)
      requires random_access_range<Base>;
 
    constexpr auto operator[](difference_type n) const
      requires random_access_range<Base>;
 
    friend constexpr bool operator==(const iterator& x, const iterator& y);
    friend constexpr bool operator<(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator<=(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>=(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr auto operator<=>(const iterator& x, const iterator& y)
      requires random_access_range<Base> &&
               three_way_comparable<iterator_t<Base>>;
 
    friend constexpr iterator operator+(const iterator& i, difference_type n)
      requires random_access_range<Base>;
    friend constexpr iterator operator+(difference_type n, const iterator& i)
      requires random_access_range<Base>;
    friend constexpr iterator operator-(const iterator& i, difference_type n)
      requires random_access_range<Base>;
    friend constexpr difference_type operator-(const iterator& x, const iterator& y)
      requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
 
    friend constexpr auto iter_move(const iterator& i)
      noexcept(/* véase a continuación */);
    friend constexpr void iter_swap(const iterator& l, const iterator& r)
      noexcept(/* véase a continuación */)
      requires indirectly_swappable<iterator_t<Base>>;
  };
}

[editar] Plantilla de clase std::ranges::adjacent_view::sentinel

namespace std::ranges {
  template<forward_range V, size_t N>
    requires view<V> && (N > 0)
  template<bool Const>
  class adjacent_view<V, N>::sentinel {
    using Base = __MaybeConst<Const, V>;                        // solo exposición
    sentinel_t<Base> end_ = sentinel_t<Base>();                 // solo exposición
    constexpr explicit sentinel(sentinel_t<Base> end);          // solo exposición
 
  public:
    sentinel() = default;
    constexpr sentinel(sentinel<!Const> i)
      requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
 
    template<bool OtherConst>
      requires sentinel_for<sentinel_t<Base>,
                            iterator_t<__MaybeConst<OtherConst, V>>>
    friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
 
    template<bool OtherConst>
      requires sized_sentinel_for<sentinel_t<Base>,
                                  iterator_t<__MaybeConst<OtherConst, V>>>
    friend constexpr range_difference_t<__MaybeConst<OtherConst, V>>
      operator-(const iterator<OtherConst>& x, const sentinel& y);
 
    template<bool OtherConst>
      requires sized_sentinel_for<sentinel_t<Base>,
                                  iterator_t<__MaybeConst<OtherConst, V>>>
    friend constexpr range_difference_t<__MaybeConst<OtherConst, V>>
      operator-(const sentinel& y, const iterator<OtherConst>& x);
  };
}

[editar] Plantilla de clase std::ranges::adjacent_transform_view

namespace std::ranges {
  template<forward_range V, copy_constructible F, size_t N>
   requires view<V> && (N > 0) && is_object_v<F> &&
            regular_invocable<F&, /* REPEAT(range_reference_t<V>, N) */...> &&
            __CanReference<invoke_result_t<F&, /* REPEAT(range_reference_t<V>, N) */...>>
  class adjacent_transform_view : public view_interface<adjacent_transform_view<V, F, N>> {
    __CopyableBox<F> fun_;                      // solo exposición
    adjacent_view<V, N> inner_;                 // solo exposición
 
    using InnerView = adjacent_view<V, N>;      // solo exposición
    template<bool Const>
      using InnerIterator = iterator_t<__MaybeConst<Const, InnerView>>;  // solo exposición
    template<bool Const>
      using InnerSentinel = sentinel_t<__MaybeConst<Const, InnerView>>;  // solo exposición
 
    // plantilla de clase adjacent_transform_view​::​iterator
    template<bool> class iterator;              // solo exposición
 
    // plantilla de clase adjacent_transform_view​::​sentinel
    template<bool> class sentinel;              // solo exposición
 
  public:
    adjacent_transform_view() = default;
    constexpr explicit adjacent_transform_view(V base, F fun);
 
    constexpr auto begin() {
      return iterator<false>(*this, inner_.begin());
    }
 
    constexpr auto begin() const
      requires range<const InnerView> &&
               regular_invocable<const F&,
                                /* REPEAT(range_reference_t<const V>, N) */...> {
      return iterator<true>(*this, inner_.begin());
    }
 
    constexpr auto end() {
      if constexpr (common_range<InnerView>) {
        return iterator<false>(*this, inner_.end());
      } else {
        return sentinel<false>(inner_.end());
      }
    }
 
    constexpr auto end() const
      requires range<const InnerView> &&
               regular_invocable<const F&,
                                /* REPEAT(range_reference_t<const V>, N) */...> {
      if constexpr (common_range<const InnerView>) {
        return iterator<true>(*this, inner_.end());
      } else {
        return sentinel<true>(inner_.end());
      }
    }
 
    constexpr auto size() requires sized_range<InnerView> {
      return inner_.size();
    }
 
    constexpr auto size() const requires sized_range<const InnerView> {
      return inner_.size();
    }
  };
}

[editar] Plantilla de clase std::ranges::adjacent_transform_view::iterator

namespace std::ranges {
  template<forward_range V, copy_constructible F, size_t N>
    requires view<V> && (N > 0) && is_object_v<F> &&
             regular_invocable<F&, /* REPEAT(range_reference_t<V>, N) */...> &&
             __CanReference<invoke_result_t<F&, /* REPEAT(range_reference_t<V>, N) */...>>
  template<bool Const>
  class adjacent_transform_view<F, V...>::iterator {
    using Parent = __MaybeConst<Const, adjacent_transform_view>;      // solo exposición
    using Base = __MaybeConst<Const, V>;                              // solo exposición
    Parent* parent_ = nullptr;                                        // solo exposición
    InnerIterator<Const> inner_;                                      // solo exposición
 
    constexpr iterator(Parent& parent, InnerIterator<Const> inner);   // solo exposición
 
  public:
    using iterator_category = /* véase a continuación */;
    using iterator_concept  = typename InnerIterator<Const>::iterator_concept;
    using value_type =
      remove_cvref_t<invoke_result_t<__MaybeConst<Const, F>&,
                                     /* REPEAT(range_reference_t<Base>, N) */...>>;
    using difference_type = range_difference_t<Base>;
 
    iterator() = default;
    constexpr iterator(iterator<!Const> i)
      requires Const && convertible_to<InnerIterator<false>, InnerIterator<Const>>;
 
    constexpr decltype(auto) operator*() const noexcept(/* véase a continuación */);
    constexpr iterator& operator++();
    constexpr iterator operator++(int);
    constexpr iterator& operator--() requires bidirectional_range<Base>;
    constexpr iterator operator--(int) requires bidirectional_range<Base>;
    constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
    constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
 
    constexpr decltype(auto) operator[](difference_type n) const
      requires random_access_range<Base>;
 
    friend constexpr bool operator==(const iterator& x, const iterator& y);
    friend constexpr bool operator<(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator<=(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>=(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr auto operator<=>(const iterator& x, const iterator& y)
      requires random_access_range<Base> && three_way_comparable<InnerIterator<Const>>;
 
    friend constexpr iterator operator+(const iterator& i, difference_type n)
      requires random_access_range<Base>;
    friend constexpr iterator operator+(difference_type n, const iterator& i)
      requires random_access_range<Base>;
    friend constexpr iterator operator-(const iterator& i, difference_type n)
      requires random_access_range<Base>;
    friend constexpr difference_type operator-(const iterator& x, const iterator& y)
      requires sized_sentinel_for<InnerIterator<Const>, InnerIterator<Const>>;
  };
}

[editar] Plantilla de clase std::ranges::adjacent_transform_view::sentinel

namespace std::ranges {
  template<forward_range V, copy_constructible F, size_t N>
    requires view<V> && (N > 0) && is_object_v<F> &&
             regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> &&
             __CanReference<invoke_result_t<F&, /* REPEAT(range_reference_t<V>, N) */...>>
  template<bool Const>
  class adjacent_transform_view<V, F, N>::sentinel {
    InnerSentinel<Const> inner_;                               // solo exposición
    constexpr explicit sentinel(InnerSentinel<Const> inner);   // solo exposición
 
  public:
    sentinel() = default;
    constexpr sentinel(sentinel<!Const> i)
      requires Const && convertible_to<InnerSentinel<false>, InnerSentinel<Const>>;
 
    template<bool OtherConst>
      requires sentinel_for<InnerSentinel<Const>, InnerSentinel<OtherConst>>
    friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
 
    template<bool OtherConst>
      requires sized_sentinel_for<InnerSentinel<Const>, InnerSentinel<OtherConst>>
    friend constexpr range_difference_t<__MaybeConst<OtherConst, InnerView>>
      operator-(const iterator<OtherConst>& x, const sentinel& y);
 
    template<bool OtherConst>
      requires sized_sentinel_for<InnerSentinel<Const>, InnerSentinel<OtherConst>>
    friend constexpr range_difference_t<__MaybeConst<OtherConst, InnerView>>
      operator-(const sentinel& x, const iterator<OtherConst>& y);
  };
}