std::random_access_iterator
| 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 -, clculo de la distancia en tiempo constante con -, o notacin de array con subndice.
Determinacin del concepto de iterador
La definicin de este concepto se especifica mediante una plantilla de alias de solo exposicin /*CONCEPTO_ITER*/.
Para determinar /*CONCEPTO_ITER*/<I>, dejemos que RASGOS_ITER<I> denote I si la especializacin 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_conceptes vlido y nombra un tipo,/*CONCEPTO_ITER*/<I>denota el tipo. - De lo contrario, si
RASGOS_ITER<I>::iterator_categoryes vlido 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 sustitucin.
Requerimientos semnticos
Sean a y b iteradores vlidos 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 ab.std::addressof(a += n)es igual astd::addressof(a).(a + n)es igual a(a += n).(a + n)es igual a(n + a).- Para dos enteros positivos cualesquiera
xey, sia + (x + y)es vlido, entoncesa + (x + y)es igual a(a + x) + y. a + 0es igual aa.- Si
(a + (n - 1))es vlido, entonces--bes igual a(a + (n - 1)). - Tanto
(b += -n)como(b -= n)son iguales aa. std::addressof(b -= n)es igual astd::addressof(b).(b - n)es igual a(b -= n).- Si
bes desreferenciable, entoncesa[n]es vlido y es igual a*b. bool(a <= b)estrue.- Cada operacin requerida tiene una complejidad de tiempo constante.
Conservacin de la igualdad
Una expresin es conservadora de igualdad si resulta en salidas iguales dadas entradas iguales.
- Las entradas de una expresin consisten en sus operandos.
- Las salidas de una expresin consisten en su resultado y todos los operandos modificados por la expresin (si es que los hay).
Cada expresin que se requiere sea conservadora de igualdad, se requiere adems que sea estable: dos evaluaciones de tal expresin con los mismos objetos de entrada debe tener salidas iguales si no se encuentra alguna modificacin interventora de esos objetos de entrada.
A menos que se indique de otra manera, cada expresin utilizada en una expresin-requiere se requiere sea conservadora de igualdad y estable, y la evaluacin de la expresin puede solamente modificar sus operandos no constantes. Los operandos que son constantes no deben ser modificados.
Variaciones de expresin implcita
Una expresin-requiere que usa una expresin que no es modificable para algn operando l-valor constante tambin requiere implcitamente variaciones adicionales de esa expresin que acepten un l-valor no constante o un r-valor (posiblemente constante) para el operando dado, a menos que tal variacin de expresin se requiera explcitamente con semnticas discrepantes. Estas variaciones de expresin implcita deben cumplir con los mismos requerimientos semnticos de la expresin declarada. No se especifica hasta qu punto una implementacin valida la sintaxis de las variaciones.
Notas
A diferencia de los requerimientos de RandomAccessIterator, el concepto random_access_iterator no requiere desreferenciacin para devolver un l-valor.
Ejemplo
Demuestra una posible implementacin 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);
}
Vase tambin
Especifica que un forward_iterator es un iterador bidireccional que puede retroceder. (concepto) |