Compartir vía


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_tC++20 Determine si un iterador devuelto para un range hace referencia a un intervalo cuya duración ha finalizado.
borrowed_subrange_tC++20 Determine si un subrange devuelto para un range hace referencia a un intervalo cuya duración ha finalizado.
danglingC++20 Indica que el iterador devuelto de una range/subrange vida útil de la duración a la range/subrange que hace referencia.
iterator_tC++20 Devuelve el tipo de iterador para el intervalo especificado.
range_difference_tC++20 Devuelve el tipo de diferencia para el iterador del intervalo especificado.
range_reference_tC++20 Devuelve el tipo de referencia para el iterador del intervalo especificado.
range_rvalue_reference_tC++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_tC++20 Devuelve el tipo usado para notificar el rango sizeespecificado.
range_value_tC++20 Devuelve el tipo de valor del iterador del intervalo especificado. O en otras palabras, el tipo de los elementos del intervalo.
sentinel_tC++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_rangees 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_rangees 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

Consulte también

<ranges>
Adaptadores de rango
Ver clases