std::distance
| Definido en el archivo de encabezado <iterator>
|
||
template< class InputIt > typename std::iterator_traits<InputIt>::difference_type distance( InputIt first, InputIt last ); |
(constexpr desde C++17) | |
Devuelve el número de saltos desde first hasta last.
Si InputIt no es RandomAccessIterator, el comportamiento no está definido si last no es alcanzable desde first.
Si InputIt es RandomAccessIterator, el comportamiento no está definido si first y last no son alcanzables uno del otro.
Parámetros
| first | - | Iterador que apunta al primer elemento. |
| last | - | Iterador que apunta al final del rango. |
| Requisitos de tipo | ||
-InputIt debe satisfacer los requisitos de InputIterator. La operación es más eficiente si InputIt cumple además los requisitos de RandomAccessIterator.
| ||
Valor de retorno
El número de incrementos necesarios para ir de first a last.
|
El valor puede ser negativo si se utilizan iteradores de acceso aleatorio y |
(desde C++11) |
Complejidad
Lineal.
Sin embargo, si InputIt cumple además los requisitos de RandomAccessIterator, la complejidad es constante.
Posible implementación
Véanse también las implementaciones en libstdc++ y libc++.
Implementación en C++98 implementation vía despacho con etiquetas, con constexpr elminado
|
|---|
namespace detail
{
template<class It>
constexpr // requerido desde C++17
typename std::iterator_traits<It>::difference_type
do_distance(It first, It last, std::input_iterator_tag)
{
typename std::iterator_traits<It>::difference_type result = 0;
while (first != last)
{
++first;
++result;
}
return result;
}
template<class It>
constexpr // requerido desde C++17
typename std::iterator_traits<It>::difference_type
do_distance(It first, It last, std::random_access_iterator_tag)
{
return last - first;
}
} // namespace detail
template<class It>
constexpr // desde C++17
typename std::iterator_traits<It>::difference_type
distance(It first, It last)
{
return detail::do_distance(first, last,
typename std::iterator_traits<It>::iterator_category());
}
|
Implementación en C++17 vía if constexpr
|
template<class It>
constexpr typename std::iterator_traits<It>::difference_type
distance(It first, It last)
{
using category = typename std::iterator_traits<It>::iterator_category;
static_assert(std::is_base_of_v<std::input_iterator_tag, category>);
if constexpr (std::is_base_of_v<std::random_access_iterator_tag, category>)
return last - first;
else
{
typename std::iterator_traits<It>::difference_type result = 0;
while (first != last)
{
++first;
++result;
}
return result;
}
}
|
Ejemplo
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> v{3, 1, 4};
std::cout << "distance(first, last) = "
<< std::distance(v.begin(), v.end()) << '\n'
<< "distance(last, first) = "
<< std::distance(v.end(), v.begin()) << '\n';
// el comportamiento no está definido (hasta LWG940)
static constexpr auto il = {3, 1, 4};
// Desde C++17 `distance` puede usarse en un contexto constexpr.
static_assert(std::distance(il.begin(), il.end()) == 3);
static_assert(std::distance(il.end(), il.begin()) == -3);
}
Salida:
distance(first, last) = 3
distance(last, first) = -3
Informes de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
| ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 940 | C++98 | La redacción no era clara para el caso en el que first se puede alcanzar desde last.
|
Se aclaró. |
Véase también
| Avanza un iterador en una distancia determinada. (función) | |
| Devuelve el número de elementos que cumplan con un criterio específico. (plantilla de función) | |
(C++20) |
Devuelve la distancia entre un iterador y un centinela, o entre el principio y el fin de un rango. (niebloid) |