Espacios de nombres
Variantes
Acciones

std::random_access_iterator

De cppreference.com
< cpp‎ | iterator
 
 
Biblioteca de iteradores
Conceptos de iteradores
random_access_iterator
(C++20)

Primitivas de iteradores
Conceptos de algoritmos y servicios
Conceptos invocables indirectos
Requerimientos comunes de algoritmos
Servicios
Adaptadores de iteradores
Iteradores de flujos
Puntos de personalización de iteradores
Operaciones de iteradores
(C++11)
(C++11)
Acceso a rangos
(C++11)(C++14)
(C++11)(C++14)
(C++17)(C++20)
(C++14)(C++14)
(C++14)(C++14)
(C++17)
(C++17)
 
Definido en el archivo de encabezado <iterator>
template<class I>

  concept random_access_iterator =
    std::bidirectional_iterator<I> &&
    std::derived_from</*CONCEPTO_ITER*/<I>, std::random_access_iterator_tag> &&
    std::totally_ordered<I> &&
    std::sized_sentinel_for<I, I> &&
    requires(I i, const I j, const std::iter_difference_t<I> n) {
      { i += n } -> std::same_as<I&>;
      { j +  n } -> std::same_as<I>;
      { n +  j } -> std::same_as<I>;
      { i -= n } -> std::same_as<I&>;
      { j -  n } -> std::same_as<I>;
      {  j[n]  } -> std::same_as<std::iter_reference_t<I>>;

    };
(desde C++20)

El concepto random_access_iterator es un refinamiento de bidirectional_iterator agregando apoyo para el avance en tiempo constante con los operadores +=, +, -=, y -, cálculo de la distancia en tiempo constante con -, o notación de array con subíndice.

Contenido

[editar] Determinación del concepto de iterador

La definición de este concepto se especifica mediante una plantilla de alias de solo exposición /*CONCEPTO_ITER*/.

Para determinar /*CONCEPTO_ITER*/<I>, dejemos que RASGOS_ITER<I> denote I si la especialización std::iterator_traits<I> se genera a partir de la plantilla principal, o std::iterator_traits<I> de lo contrario:

  • Si RASGOS_ITER<I>::iterator_concept es válido y nombra un tipo, /*CONCEPTO_ITER*/<I> denota el tipo.
  • De lo contrario, si RASGOS_ITER<I>::iterator_category es válido y nombra un tipo, /*CONCEPTO_ITER*/<I> denota el tipo.
  • De lo contrario, si std::iterator_traits <I> se genera a partir de la plantilla principal, /*CONCEPTO_ITER*/<I> denota std::random_access_iterator_tag.
  • De lo contrario, /*CONCEPTO_ITER*/<I> no denota un tipo y da como resultado un error de sustitución.

[editar] Requerimientos semánticos

Sean a y b iteradores válidos de tipo I tal que b se puede alcanzar desde a, y sea n un valor de tipo std::iter_difference_t<I> igual a b - a. Se modela random_access_iterator<I> solo si todos los conceptos que subsume se modelan, y:

  • (a += n) es igual a b.
  • std::addressof(a += n) es igual a std::addressof(a).
  • (a + n) es igual a (a += n).
  • (a + n) es igual a (n + a).
  • Para dos enteros positivos cualesquiera x e y, si a + (x + y) es válido, entonces a + (x + y) es igual a (a + x) + y.
  • a + 0 es igual a a.
  • Si (a + (n - 1)) es válido, entonces --b es igual a (a + (n - 1)).
  • Tanto (b += -n) como (b -= n) son iguales a a.
  • std::addressof(b -= n) es igual a std::addressof(b).
  • (b - n) es igual a (b -= n).
  • Si b es desreferenciable, entonces a[n] es válido y es igual a *b.
  • bool(a <= b) es true.
  • Cada operación requerida tiene una complejidad de tiempo constante.

[editar] Conservación de la igualdad

Una expresión es conservadora de igualdad si resulta en salidas iguales dadas entradas iguales.

  • Las entradas de una expresión consisten en sus operandos.
  • Las salidas de una expresión consisten en su resultado y todos los operandos modificados por la expresión (si es que los hay).

Cada expresión que se requiere sea conservadora de igualdad, se requiere además que sea estable: dos evaluaciones de tal expresión con los mismos objetos de entrada debe tener salidas iguales si no se encuentra alguna modificación interventora de esos objetos de entrada.

A menos que se indique de otra manera, cada expresión utilizada en una expresión-requiere se requiere sea conservadora de igualdad y estable, y la evaluación de la expresión puede solamente modificar sus operandos no constantes. Los operandos que son constantes no deben ser modificados.

[editar] Variaciones de expresión implícita

Una expresión-requiere que usa una expresión que no es modificable para algún operando l-valor constante también requiere implícitamente variaciones adicionales de esa expresión que acepten un l-valor no constante o un r-valor (posiblemente constante) para el operando dado, a menos que tal variación de expresión se requiera explícitamente con semánticas discrepantes. Estas variaciones de expresión implícita deben cumplir con los mismos requerimientos semánticos de la expresión declarada. No se especifica hasta qué punto una implementación valida la sintaxis de las variaciones.

[editar] Notas

A diferencia de los requerimientos de RandomAccessIterator, el concepto random_access_iterator no requiere desreferenciación para devolver un l-valor.

[editar] Ejemplo

Demuestra una posible implementación de std::distance mediante conceptos de C++20.

#include <iterator>
 
namespace cxx20 {
   template<std::input_or_output_iterator Iter>
   constexpr std::iter_difference_t<Iter> distance(Iter first, Iter last)
   {
       if constexpr(std::random_access_iterator<Iter>)
           return last - first;
       else
       {
           std::iter_difference_t<Iter> result{};
           for (;first != last;++first)
               ++result;
           return result;
       }
   }
}
 
int main() {
    static constexpr auto il = { 3, 1, 4 };
    static_assert(cxx20::distance(il.begin(), il.end()) == 3);
    static_assert(cxx20::distance(il.end(), il.begin()) == -3);
}


[editar] Véase también

Especifica que un forward_iterator es un iterador bidireccional que puede retroceder.
(concepto) [editar]