<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_t C++20 |
Determinare se un iteratore restituito per un range fa riferimento a un intervallo la cui durata è terminata. |
borrowed_subrange_t C++20 |
Determinare se un subrange oggetto restituito per un range fa riferimento a un intervallo la cui durata è terminata. |
dangling C++20 |
Indica che l'iteratore restituito di un range /subrange oggetto dura la durata dell'oggetto range /subrange a cui fa riferimento. |
iterator_t C++20 |
Restituisce il tipo di iteratore per l'intervallo specificato. |
range_difference_t C++20 |
Restituisce il tipo di differenza per l'iteratore dell'intervallo specificato. |
range_reference_t C++20 |
Restituisce il tipo di riferimento per l'iteratore dell'intervallo specificato. |
range_rvalue_reference_t C++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_t C++20 |
Restituisce il tipo utilizzato per segnalare l'oggetto dell'intervallo size specificato. |
range_value_t C++20 |
Restituisce il tipo di valore dell'iteratore dell'intervallo specificato. In altre parole, il tipo degli elementi nell'intervallo. |
sentinel_t C++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_range
oggetto , 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_range
oggetto , 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