Plantillas de alias <ranges>
Una plantilla de alias es un alias para otro tipo, que puede hacer que el código sea más legible. Por ejemplo, el alias siguiente, conditional_t
, es un alias para o borrowed_range
dangling
intervalo, en función del tipo de range
que se pasa:
// requires /std:c++20, or later
#include <iostream>
#include <list>
#include <span>
#include <algorithm>
#include <ranges>
#include <type_traits>
using namespace std;
// Define an alias template called my_iterator_t
// If the provided range R is a borrowed_range, then the
// returned type is iterator_t<R>; otherwise, ranges::dangling
template<ranges::range R>
using my_iterator_t = conditional_t<
ranges::borrowed_range<R>,
ranges::iterator_t<R>, ranges::dangling>;
int main()
{
my_iterator_t<list<int>> aDanglingRange; // list<> isn't a borrowed_range
constexpr bool same = same_as<
decltype(aDanglingRange),
ranges::dangling>; // true
my_iterator_t<span<int, 5>> anIterator_t; // span<> is a borrowed_range
constexpr bool same2 = same_as<
decltype(anIterator_t),
ranges::iterator_t<span<int, 5>>>; // true
cout << boolalpha << same << "," << same2; // outputs true, true
}
Para obtener más información sobre las plantillas de alias, vea Aliases y definiciones de tipo.
El <algorithm>
encabezado define las siguientes plantillas de alias que determinan los tipos de iteradores y sentinels para :range
Plantilla de alias | Descripción |
---|---|
borrowed_iterator_t C++20 |
Determine si un iterador devuelto para un range hace referencia a un intervalo cuya duración ha finalizado. |
borrowed_subrange_t C++20 |
Determine si un subrange devuelto para un range hace referencia a un intervalo cuya duración ha finalizado. |
dangling C++20 |
Indica que el iterador devuelto de una range /subrange vida útil de la duración a la range /subrange que hace referencia. |
iterator_t C++20 |
Devuelve el tipo de iterador para el intervalo especificado. |
range_difference_t C++20 |
Devuelve el tipo de diferencia para el iterador del intervalo especificado. |
range_reference_t C++20 |
Devuelve el tipo de referencia para el iterador del intervalo especificado. |
range_rvalue_reference_t C++20 |
Devuelve el tipo de referencia rvalue para el iterador del intervalo especificado. En otras palabras, el tipo de referencia rvalue de los elementos del intervalo. |
range_size_t C++20 |
Devuelve el tipo usado para notificar el rango size especificado. |
range_value_t C++20 |
Devuelve el tipo de valor del iterador del intervalo especificado. O en otras palabras, el tipo de los elementos del intervalo. |
sentinel_t C++20 |
Devuelve el tipo de sentinel para el intervalo especificado. |
borrowed_iterator_t
Cuando se llama a una función de algoritmo que devuelve un iterador con un argumento rvalue range
, la duración del intervalo podría terminar después de la llamada. Esto significa que el iterador devuelto podría hacer referencia a elementos cuya duración ha finalizado. El uso de un iterador pendiente da como resultado un comportamiento indefinido.
Este alias de plantilla devuelve ranges::dangling
para indicar que se trata de la situación del argumento de intervalo especificado, o std::ranges::iterator_t<R>
para indicar que es seguro usar el iterador devuelto porque el intervalo al que hace referencia a modelos borrowed_range
o el intervalo se pasó como un valor lvalue.
template<ranges::range R>
using borrowed_iterator_t = conditional_t<ranges::borrowed_range<R>,
ranges::iterator_t<R>, ranges::dangling>;
Parámetros
R
Intervalo que se va a probar.
Comentarios
La duración de un intervalo rvalue puede terminar después de una llamada de función si los modelos borrowed_range
de intervalo o no. Si es , borrowed_range
es posible que pueda seguir usando los iteradores con un comportamiento bien definido, independientemente de cuándo finalice la duración del intervalo.
Los casos en los que esto no es true son, por ejemplo, para contenedores como vector
o list
porque cuando finaliza la duración del contenedor, los iteradores harían referencia a elementos que se han destruido.
Puede seguir usando los iteradores de un borrowed_range
, por ejemplo, para un view
como iota_view<int>{0, 42}
cuyos iteradores están sobre el conjunto de valores que no están sujetos a ser destruidos porque se generan a petición.
Si se pasa una función de algoritmo a un intervalo cuyos iteradores dependen de su duración, ranges::dangling
se devuelve en lugar de un iterador o un subrango, por lo que se detecta un posible uso incorrecto en tiempo de compilación.
Ejemplo: borrowed_iterator_t
En el ejemplo siguiente se muestra cómo borrowed_iterator_t
detecta un iterador pendiente. La función ranges::max_element()
usa este alias de plantilla para determinar el tipo de valor devuelto:
// requires /std:c++20, or later
#include <vector>
#include <span>
#include <ranges>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
// Not dangling ------------------
int a[] = {0,1,2,3};
// not dangling even though an rvalue because span models ranges::borrowed
auto result1 = ranges::max_element(span{a});
cout << boolalpha << ranges::borrowed_range<decltype(span{a})> << endl; // outputs true because the temporary models ranges::borrowed
cout << same_as<decltype(result1), ranges::dangling> << endl; // outputs false because the result isn't dangling
vector<int> v{0,1,2,3}; // doesn't model ranges::borrowed
auto result2 = ranges::max_element(v); // Yet not dangling because passed as an lvalue
cout << same_as<decltype(result2), ranges::dangling> << endl; // outputs false because the result isn't dangling
// Dangling ------------------
auto result3 = ranges::max_element(vector{0,1,2,3}); // dangling because vector doesn't model ranges::borrowed and is passed as an rvalue
cout << same_as<decltype(result3), ranges::dangling>; // outputs true because the result is dangling
}
true
false
false
true
borrowed_subrange_t
Cuando se llama a una función de algoritmo que devuelve un subrange
con un argumento rvalue range
, la duración del intervalo podría terminar después de la llamada. Esto significa que el devuelto subrange
podría hacer referencia a elementos cuya duración ha finalizado. El uso de un elemento subrange
pendiente da como resultado un comportamiento indefinido.
Este alias de plantilla devuelve ranges::dangling
para indicar que esto podría ser la situación del argumento de intervalo especificado o subrange<ranges::iterator_t<R>>
para indicar que es seguro usar el subrango devuelto porque el intervalo cuyos elementos hace referencia a modelos borrowed_range
o el intervalo se pasó como un valor lvalue.
template<ranges::range R>
using borrowed_subrange_t = conditional_t<ranges::borrowed_range<R>,
ranges::subrange<ranges::iterator_t<R>>, ranges::dangling>;
Parámetros
R
Intervalo que se va a probar.
Comentarios
La duración de un intervalo rvalue puede terminar después de una llamada de función si los modelos borrowed_range
de intervalo o no. Si es , borrowed_range
es posible que pueda seguir usando los iteradores con un comportamiento bien definido, independientemente de cuándo finalice la duración del intervalo.
Los casos en los que esto no es true son, por ejemplo, para contenedores como vector
o list
porque cuando finaliza la duración del contenedor, los iteradores harían referencia a elementos que se han destruido.
Puede seguir usando los iteradores de un borrowed_range
, por ejemplo, para un view
como iota_view<int>{0, 42}
cuyos iteradores están sobre el conjunto de valores que no están sujetos a ser destruidos porque se generan a petición.
Si se pasa una función de algoritmo a un intervalo cuyos iteradores dependen de su duración, ranges::dangling
se devuelve en lugar de un subrango para que se detecte un uso incorrecto potencial en tiempo de compilación.
Ejemplo: borrowed_subrange_t
En el ejemplo siguiente se muestra cómo borrowed_subrange_t
detecta un iterador pendiente porque equal_range()
y max_element
usa este alias de plantilla para determinar el tipo de valor devuelto:
// requires /std:c++20, or later
#include <vector>
#include <iostream>
#include <algorithm>
#include <span>
#include <ranges>
int main()
{
using namespace std;
// Not dangling ------------------
vector vec{0, 1, 1, 2};
auto result1 = ranges::equal_range(span{vec}, 1); // not dangling even though passing as an rvalue because span models borrowed_range
cout << boolalpha << ranges::borrowed_range<decltype(span{vec})> << endl; // true because the temporary is a borrowed range
cout << boolalpha << same_as<decltype(result1), ranges::dangling> << endl; // false because the result isn't dangling
// result2 isn't dangling even though vec doesn't model ranges::borrowed because it's an lvalue
auto result2 = ranges::max_element(vec);
cout << boolalpha << ranges::borrowed_range<decltype(vec)> << endl; // false because vector isn't a borrowed_range
cout << boolalpha << same_as<decltype(result2), ranges::dangling> << endl; // false because the result isn't dangling
// Dangling -----------------------
// result3 is dangling because the temporary is an rvalue that doesn't model borrowed_range
auto result3 = ranges::max_element(vector{0,1,1,2});
cout << boolalpha << same_as<decltype(result3), ranges::dangling> << endl; // true because the result is dangling
}
true
false
false
false
true
dangling
Si se llama a una función de algoritmo que devuelve un iterador o un subrange
con un argumento rvalue range
, la duración del argumento de intervalo podría terminar después de la llamada. Esto significa que el iterador devuelto o subrange
podría hacer referencia a elementos cuya duración ha finalizado. El uso de un iterador pendiente o subrange
da como resultado un comportamiento indefinido.
Si se pasa una función de algoritmo a un intervalo cuyos iteradores dependen de su duración, ranges::dangling
se devuelve en lugar de un iterador o un subrango para que se detecte un posible uso incorrecto en tiempo de compilación.
1) constexpr dangling() noexcept = default;
2) template<class... Args>
constexpr dangling(Args&&...) noexcept {}
Parámetros
Args
Número variable de novoid
tipos. No tienen ningún efecto. Los argumentos son una comodidad para que no necesite rutas de acceso de código diferentes para controlar la construcción del tipo de iterador frente al dangling
tipo. Esto resulta útil cuando el valor pasado indica que dangling
se debe devolver en lugar de un iterador.
Ejemplo: dangling
En el ejemplo siguiente se muestra cómo max_element
detecta un iterador pendiente.
// requires /std:c++20, or later
#include <vector>
#include <iostream>
#include <ranges>
#include <algorithm>
using namespace std;
int main()
{
auto result1 = ranges::max_element(vector{1,2,3}); // dangling because vector doesn't model ranges::borrowed and is passed as an rvalue
cout << boolalpha << same_as<decltype(result1), ranges::dangling> << endl; // outputs true because the result is dangling
vector<int> v{3,4,5};
auto result2 = ranges::max_element(v); // Not dangling because passed as an lvalue
cout << same_as<decltype(result2), ranges::dangling>; // outputs false because the result isn't dangling
}
true
false
iterator_t
Este alias de plantilla devuelve el tipo de iterador usado para iterar sobre el tipo de intervalo proporcionado.
template<class T>
using iterator_t = decltype(ranges::begin(declval<T&>()));
Parámetros
T
Tipo de intervalo para el que se va a obtener el tipo de iterador.
Ejemplo: iterator_t
En el ejemplo siguiente se muestra cómo iterator_t
se puede usar para declarar un iterador para un vector:
// requires /std:c++20, or later
#include <vector>
#include <ranges>
#include <iostream>
int main()
{
using namespace std;
vector<int> v{1,2,3};
ranges::iterator_t<decltype(v)> it = v.begin();
cout << *it << "\n"; // outputs 1
cout << typeid(it).name(); // outputs class _Vector_iterator<class _Vector_val<struct _Simple_types<int>>>
}
1
class std::_Vector_iterator<class std::_Vector_val<struct std::_Simple_types<int> > >
range_difference_t
Devuelve el tipo de diferencia para el iterador del intervalo especificado.
template<range R>
using range_difference_t = iter_difference_t<iterator_t<R>>;
Parámetros
R
Intervalo cuyo iterador proporcionará el tipo de diferencia.
Ejemplo: range_difference_t
En el ejemplo siguiente se muestra cómo range_difference_t
se usa para mantener la distancia entre los elementos de un intervalo:
// requires /std:c++20, or later
#include <vector>
#include <ranges>
#include <iostream>
int main()
{
using namespace std;
vector<int> v{1,2,3};
auto findIt = ranges::find(v, 2);
// type of distance is ptrdiff_t
ranges::range_difference_t<decltype(v)> distance = ranges::distance(v.begin(), findIt);
cout << distance << endl; // outputs 1
}
1
range_reference_t
Devuelve el tipo de referencia para el iterador del intervalo especificado. Es decir, el tipo de referencia de los elementos del intervalo.
template <range R>
using range_reference_t = iter_reference_t<ranges::iterator_t<R>>;
Parámetros
R
Intervalo para el que se devuelve el tipo de referencia de su tipo de iterador.
Ejemplo: range_reference_t
En el ejemplo siguiente se muestra range_reference_t
cómo hacer referencia al tipo de los elementos de un intervalo:
// requires /std:c++20, or later
#include <vector>
#include <ranges>
#include <iostream>
int main()
{
using namespace std;
vector<int> v{1,2,3};
ranges::range_reference_t<decltype(v)> ref = v[0];
cout << ref << endl; // outputs 1
cout << typeid(ref).name() << endl; // outputs int
}
1
int
range_rvalue_reference_t
Devuelve el tipo de referencia rvalue para el iterador del intervalo especificado. En otras palabras, el tipo de referencia rvalue de los elementos del intervalo.
template <range R>
using range_rvalue_reference_t = iter_reference_t<ranges::iterator_t<R>>;
Parámetros
R
Intervalo para obtener el tipo de referencia rvalue a su tipo de iterador.
Ejemplo: range_rvalue_reference_t
En el ejemplo siguiente se muestra range_rvalue_reference_t
cómo hacer referencia a un tipo rvalue de los elementos de un intervalo:
// requires /std:c++20, or later
#include <vector>
#include <ranges>
#include <iostream>
int main()
{
using namespace std;
vector<int> v{1,2,3};
ranges::range_rvalue_reference_t<decltype(v)> elementRvalueType = v[0] * 10; // elementRvalueType is int&&
cout << elementRvalueType << endl; // outputs 10
cout << typeid(elementRvalueType).name() << endl; // outputs int
}
10
int
range_size_t
Devuelve el tipo de la size
función para el especificado sized_range
.
template <range R>
using range_size_t = iter_reference_t<ranges::iterator_t<R>>;
Parámetros
R
Intervalo para obtener el tipo de su size
función.
Ejemplo: range_size_t
En el ejemplo siguiente se muestra range_size_t
cómo hacer referencia al número de elementos de un intervalo:
// requires /std:c++20, or later
#include <vector>
#include <iostream>
#include <ranges>
int main()
{
using namespace std;
vector<int> v{1,2,3};
ranges::range_size_t<decltype(v)> size = v.size();
cout << size << endl; // outputs 3
cout << typeid(size).name(); // outputs unsigned __int64
}
3
unsigned __int64
range_value_t
Devuelve el tipo de valor del iterador del intervalo especificado. O en otras palabras, el tipo de los elementos del intervalo.
template <ranges::range R>
using range_value_t = iter_value_t<ranges::iterator_t<R>>;
Parámetros
R
Intervalo para obtener el tipo de valor de su iterador.
Ejemplo: range_value_t
En el ejemplo siguiente se muestra cómo range_value_t
hace referencia al tipo de elementos de un intervalo:
// requires /std:c++20, or later
#include <vector>
#include <ranges>
#include <iostream>
int main()
{
using namespace std;
vector<int> v{1,2,3};
ranges::range_value_t<decltype(v)> elementType = v[2]; // elementType is an int
cout << elementType << endl; // outputs 3
cout << typeid(elementType).name() << endl; // outputs int
}
3
unsigned int
sentinel_t
Devuelve el tipo de sentinel para el intervalo especificado.
template <range R>
using sentinel_t = decltype(ranges::end(declval<R&>()));
Parámetros
R
Intervalo para el que se va a obtener el tipo centinela.
Ejemplo: sentinel_t
En el ejemplo siguiente se muestra cómo usar sentinel_t
para determinar si el tipo de iterador y el tipo sentinel son los mismos:
// requires /std:c++20, or later
#include <iostream>
#include <list>
#include <ranges>
int main()
{
using namespace std;
list myList{1, 2, 3};
ranges::subrange count = std::views::counted(myList.begin(), myList.size());
ranges::iterator_t<decltype(count)> first;
ranges::sentinel_t<decltype(count)> last;
// The iterator type and the sentinel type of a subrange
// obtained from views::counted are not the same
cout << boolalpha << is_same<decltype(first), decltype(last)>::value << endl; // outputs false
cout << "iter: " << typeid(first).name() << "\n\n end: " << typeid(last).name() << endl;
}
false
iter: class std::counted_iterator<class std::_List_iterator<class std::_List_val<struct std::_List_simple_types<int> > > >
end: struct std::default_sentinel_t