Condividi tramite


<ranges> modelli alias

Un modello di alias è un alias per un altro tipo, che può rendere il codice più leggibile. Ad esempio, l'alias seguente, conditional_t, è un alias per o dangling borrowed_range intervallo, a seconda del tipo di range passato:

// 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
}

Per altre informazioni sui modelli di alias, vedere Alias e typedef.

L'intestazione <algorithm> definisce i modelli di alias seguenti che determinano i tipi di iteratori e sentinelle per un oggetto range:

Modello di alias Descrizione
borrowed_iterator_tC++20 Determinare se un iteratore restituito per un range fa riferimento a un intervallo la cui durata è terminata.
borrowed_subrange_tC++20 Determinare se un subrange oggetto restituito per un range fa riferimento a un intervallo la cui durata è terminata.
danglingC++20 Indica che l'iteratore restituito di un range/subrange oggetto dura la durata dell'oggetto range/subrange a cui fa riferimento.
iterator_tC++20 Restituisce il tipo di iteratore per l'intervallo specificato.
range_difference_tC++20 Restituisce il tipo di differenza per l'iteratore dell'intervallo specificato.
range_reference_tC++20 Restituisce il tipo di riferimento per l'iteratore dell'intervallo specificato.
range_rvalue_reference_tC++20 Restituisce il tipo di riferimento rvalue per l'iteratore dell'intervallo specificato. In altre parole, il tipo di riferimento rvalue degli elementi dell'intervallo.
range_size_tC++20 Restituisce il tipo utilizzato per segnalare l'oggetto dell'intervallo sizespecificato.
range_value_tC++20 Restituisce il tipo di valore dell'iteratore dell'intervallo specificato. In altre parole, il tipo degli elementi nell'intervallo.
sentinel_tC++20 Restituisce il tipo di sentinel per l'intervallo specificato.

borrowed_iterator_t

Quando una funzione di algoritmo che restituisce un iteratore viene chiamata con un argomento rvalue range , la durata dell'intervallo potrebbe terminare dopo la chiamata. Ciò significa che l'iteratore restituito può fare riferimento a elementi la cui durata è terminata. L'uso di un iteratore dangling comporta un comportamento non definito.

Questo alias di modello restituisce ranges::dangling per indicare che si tratta della situazione per l'argomento intervallo specificato o std::ranges::iterator_t<R> per indicare che è sicuro usare l'iteratore restituito perché l'intervallo fa riferimento a modelli borrowed_range o l'intervallo è stato passato come lvalue.

template<ranges::range R>
using borrowed_iterator_t = conditional_t<ranges::borrowed_range<R>,
    ranges::iterator_t<R>, ranges::dangling>;

Parametri

R
Intervallo da testare.

Osservazioni:

La durata di un intervallo rvalue può terminare dopo una chiamata di funzione indipendentemente dal fatto che i modelli borrowed_range di intervallo siano o meno. Se si tratta di , borrowed_rangeè possibile continuare a usare gli iteratori con un comportamento ben definito indipendentemente dal termine della durata dell'intervallo.

I casi in cui questo non è vero sono, ad esempio, per contenitori come vector o list perché al termine della durata del contenitore, gli iteratori fanno riferimento a elementi eliminati definitivamente.

È possibile continuare a usare gli iteratori per un borrowed_rangeoggetto , ad esempio per un view oggetto come iota_view<int>{0, 42} i cui iteratori sono sovraimpostati su set di valori che non sono soggetti a essere eliminati definitivamente perché vengono generati su richiesta.

Se una funzione dell'algoritmo viene passata a un intervallo i cui iteratori dipendono dalla durata, ranges::dangling viene restituito invece di un iteratore o di un intervallo secondario, quindi viene rilevato un potenziale uso improprio in fase di compilazione.

Esempio: borrowed_iterator_t

Nell'esempio seguente viene illustrato come borrowed_iterator_t rilevare un iteratore dangling. La funzione ranges::max_element() usa questo alias di modello per determinare il tipo restituito:

// 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

Quando una funzione di algoritmo che restituisce un subrange oggetto viene chiamato con un argomento rvalue range , la durata dell'intervallo potrebbe terminare dopo la chiamata. Ciò significa che l'oggetto restituito subrange può fare riferimento agli elementi la cui durata è terminata. L'uso di un elemento dangling subrange comporta un comportamento indefinito.

Questo alias di modello restituisce ranges::dangling per indicare che potrebbe trattarsi della situazione per l'argomento intervallo specificato oppure subrange<ranges::iterator_t<R>> per indicare che è sicuro usare il sottorange restituito perché l'intervallo i cui elementi fa riferimento ai modelli borrowed_range o l'intervallo è stato passato come lvalue.

template<ranges::range R>
using borrowed_subrange_t = conditional_t<ranges::borrowed_range<R>,
    ranges::subrange<ranges::iterator_t<R>>, ranges::dangling>;

Parametri

R
Intervallo da testare.

Osservazioni:

La durata di un intervallo rvalue può terminare dopo una chiamata di funzione indipendentemente dal fatto che i modelli borrowed_range di intervallo siano o meno. Se si tratta di , borrowed_rangeè possibile continuare a usare gli iteratori con un comportamento ben definito indipendentemente dal termine della durata dell'intervallo.

I casi in cui questo non è vero sono, ad esempio, per contenitori come vector o list perché al termine della durata del contenitore, gli iteratori fanno riferimento a elementi eliminati definitivamente.

È possibile continuare a usare gli iteratori per un borrowed_rangeoggetto , ad esempio per un view oggetto come iota_view<int>{0, 42} i cui iteratori sono sovraimpostati su set di valori che non sono soggetti a essere eliminati definitivamente perché vengono generati su richiesta.

Se una funzione di algoritmo viene passata a un intervallo i cui iteratori dipendono dalla durata, ranges::dangling viene restituito invece di un intervallo secondario in modo che venga rilevato un potenziale uso improprio in fase di compilazione.

Esempio: borrowed_subrange_t

Nell'esempio seguente viene illustrato come borrowed_subrange_t rilevare un iteratore dangling perché equal_range() e max_element usare questo alias di modello per determinare il tipo restituito:

// 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

Se una funzione dell'algoritmo che restituisce un iteratore o un subrange oggetto viene chiamato con un argomento rvalue range , la durata dell'argomento intervallo potrebbe terminare dopo la chiamata. Ciò significa che l'iteratore restituito o subrange può fare riferimento a elementi la cui durata è terminata. L'uso di un iteratore dangling o subrange comporta un comportamento indefinito.

Se una funzione di algoritmo viene passata a un intervallo i cui iteratori dipendono dalla durata, ranges::dangling viene restituito invece di un iteratore o di un intervallo secondario in modo che venga rilevato un potenziale uso improprio in fase di compilazione.

1) constexpr dangling() noexcept = default;
2) template<class... Args>
constexpr dangling(Args&&...) noexcept {}

Parametri

Args
Numero variabile di tipi diversivoid . Non hanno alcun effetto. Gli argomenti sono pratici in modo che non siano necessari percorsi di codice diversi per gestire la costruzione del tipo iteratore rispetto al dangling tipo. Ciò è utile quando il valore passato indica che dangling deve essere restituito anziché un iteratore.

Esempio: dangling

Nell'esempio seguente viene illustrato come max_element rilevare un iteratore dangling.

// 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

Questo alias modello restituisce il tipo di iteratore usato per scorrere il tipo di intervallo specificato.

template<class T>
using iterator_t = decltype(ranges::begin(declval<T&>()));

Parametri

T
Tipo di intervallo per cui ottenere il tipo di iteratore.

Esempio: iterator_t

L'esempio seguente illustra come iterator_t usare per dichiarare un iteratore per un vettore:

// 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

Restituisce il tipo di differenza per l'iteratore dell'intervallo specificato.

template<range R>
using range_difference_t = iter_difference_t<iterator_t<R>>;

Parametri

R
Intervallo il cui iteratore fornirà il tipo di differenza.

Esempio: range_difference_t

L'esempio seguente mostra come range_difference_t viene usato per mantenere la distanza tra gli elementi in un intervallo:

// 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

Restituisce il tipo di riferimento per l'iteratore dell'intervallo specificato. In altre parole, il tipo di riferimento degli elementi dell'intervallo.

template <range R>
using range_reference_t = iter_reference_t<ranges::iterator_t<R>>;

Parametri

R
Intervallo per il quale viene restituito il tipo di riferimento del tipo iteratore.

Esempio: range_reference_t

Nell'esempio seguente viene illustrato range_reference_t il riferimento al tipo degli elementi in un intervallo:

// 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

Restituisce il tipo di riferimento rvalue per l'iteratore dell'intervallo specificato. In altre parole, il tipo di riferimento rvalue degli elementi dell'intervallo.

template <range R>
using range_rvalue_reference_t = iter_reference_t<ranges::iterator_t<R>>;

Parametri

R
Intervallo per ottenere il tipo riferimento rvalue al tipo iteratore.

Esempio: range_rvalue_reference_t

L'esempio seguente mostra il range_rvalue_reference_t riferimento a un tipo rvalue degli elementi in un intervallo:

// 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

Restituisce il tipo della size funzione per l'oggetto specificato sized_range.

template <range R>
using range_size_t = iter_reference_t<ranges::iterator_t<R>>;

Parametri

R
Intervallo per ottenere il tipo della relativa size funzione.

Esempio: range_size_t

Nell'esempio seguente viene illustrato range_size_t il riferimento al numero di elementi in un intervallo:

// 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

Restituisce il tipo di valore dell'iteratore dell'intervallo specificato. In altre parole, il tipo degli elementi nell'intervallo.

template <ranges::range R>
using range_value_t = iter_value_t<ranges::iterator_t<R>>;

Parametri

R
Intervallo per ottenere il tipo di valore del relativo iteratore.

Esempio: range_value_t

L'esempio seguente mostra come range_value_t fa riferimento al tipo di elementi in un intervallo:

// 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

Restituisce il tipo di sentinel per l'intervallo specificato.

template <range R>
using sentinel_t = decltype(ranges::end(declval<R&>()));

Parametri

R
Intervallo per cui ottenere il tipo sentinel.

Esempio: sentinel_t

L'esempio seguente mostra l'uso sentinel_t di per determinare se il tipo di iteratore e il tipo di sentinel sono uguali:

// 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

Vedi anche

<ranges>
Adattatori di intervallo
Visualizzare le classi