<ranges>
modèles d’alias
Un modèle d’alias est un alias pour un autre type, ce qui peut rendre le code plus lisible. Par exemple, l’alias suivant, conditional_t
est un alias pour l’une borrowed_range
ou dangling
l’autre plage, selon le type de range
celui-ci passé :
// 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
}
Pour plus d’informations sur les modèles d’alias, consultez Alias et typedefs.
L’en-tête <algorithm>
définit les modèles d’alias suivants qui déterminent les types d’itérateurs et de sentinelles pour un range
:
Modèle d’alias | Description |
---|---|
borrowed_iterator_t C++20 |
Déterminez si un itérateur retourné pour une range plage fait référence à une plage dont la durée de vie a pris fin. |
borrowed_subrange_t C++20 |
Déterminez si un subrange retour pour une range plage fait référence à une plage dont la durée de vie a pris fin. |
dangling C++20 |
Indique que l’itérateur retourné d’une durée de vie de celle-ci/subrange range fait référence.range /subrange |
iterator_t C++20 |
Retourne le type d’itérateur pour la plage spécifiée. |
range_difference_t C++20 |
Retourne le type de différence pour l’itérateur de la plage spécifiée. |
range_reference_t C++20 |
Retourne le type de référence de l’itérateur de la plage spécifiée. |
range_rvalue_reference_t C++20 |
Retourne le type de référence rvalue pour l’itérateur de la plage spécifiée. En d’autres termes, le type de référence rvalue des éléments de la plage. |
range_size_t C++20 |
Retourne le type utilisé pour signaler la plage size spécifiée. |
range_value_t C++20 |
Retourne le type valeur de l’itérateur de plage spécifié. En d’autres termes, le type des éléments de la plage. |
sentinel_t C++20 |
Retourne le type sentinelle de la plage spécifiée. |
borrowed_iterator_t
Lorsqu’une fonction d’algorithme qui retourne un itérateur est appelée avec un argument rvalue range
, la durée de vie de la plage peut se terminer après l’appel. Cela signifie que l’itérateur retourné peut faire référence à des éléments dont les durées de vie ont pris fin. L’utilisation d’un itérateur dérangé entraîne un comportement non défini.
Cet alias de modèle retourne ranges::dangling
pour indiquer qu’il s’agit de la situation de l’argument de plage donné ou std::ranges::iterator_t<R>
d’indiquer qu’il est sûr d’utiliser l’itérateur retourné, car la plage qu’elle fait référence aux modèles borrowed_range
ou à la plage a été passée en tant que lvalue.
template<ranges::range R>
using borrowed_iterator_t = conditional_t<ranges::borrowed_range<R>,
ranges::iterator_t<R>, ranges::dangling>;
Paramètres
R
Plage à tester.
Notes
La durée de vie d’une plage rvalue peut se terminer par un appel de fonction, que les modèles borrowed_range
de plage soient ou non. S’il s’agit d’un borrowed_range
, vous pouvez continuer à utiliser les itérateurs avec un comportement bien défini, quel que soit le moment de la fin de la durée de vie de la plage.
Les cas où cela n’est pas vrai sont, par exemple, pour les conteneurs comme vector
ou list
parce que lorsque la durée de vie du conteneur se termine, les itérateurs font référence aux éléments qui ont été détruits.
Vous pouvez continuer à utiliser les itérateurs pour un borrowed_range
, par exemple, pour un view
type dont iota_view<int>{0, 42}
les itérateurs sont sur un ensemble de valeurs qui ne sont pas soumises à la destruction, car elles sont générées à la demande.
Si une fonction d’algorithme est passée à une plage dont les itérateurs dépendent de sa durée de vie, ranges::dangling
est retournée au lieu d’un itérateur ou d’une sous-plage, une mauvaise utilisation potentielle est donc détectée au moment de la compilation.
Exemple : borrowed_iterator_t
L’exemple suivant montre comment borrowed_iterator_t
détecter un itérateur dérangé. La fonction ranges::max_element()
utilise cet alias de modèle pour déterminer le type de retour :
// 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
Lorsqu’une fonction d’algorithme qui retourne une subrange
valeur est appelée avec un argument rvalue range
, la durée de vie de la plage peut se terminer après l’appel. Cela signifie que le retour subrange
peut faire référence aux éléments dont les durées de vie ont pris fin. L’utilisation d’un déchaînement subrange
entraîne un comportement non défini.
Cet alias de modèle retourne ranges::dangling
pour indiquer qu’il peut s’agir de la situation de l’argument de plage donné, ou subrange<ranges::iterator_t<R>>
pour indiquer qu’il est sûr d’utiliser la sous-plage retournée, car la plage dont il fait référence aux modèles borrowed_range
ou la plage a été passée en tant que lvalue.
template<ranges::range R>
using borrowed_subrange_t = conditional_t<ranges::borrowed_range<R>,
ranges::subrange<ranges::iterator_t<R>>, ranges::dangling>;
Paramètres
R
Plage à tester.
Notes
La durée de vie d’une plage rvalue peut se terminer par un appel de fonction, que les modèles borrowed_range
de plage soient ou non. S’il s’agit d’un borrowed_range
, vous pouvez continuer à utiliser les itérateurs avec un comportement bien défini, quel que soit le moment de la fin de la durée de vie de la plage.
Les cas où cela n’est pas vrai sont, par exemple, pour les conteneurs comme vector
ou list
parce que lorsque la durée de vie du conteneur se termine, les itérateurs font référence aux éléments qui ont été détruits.
Vous pouvez continuer à utiliser les itérateurs pour un borrowed_range
, par exemple, pour un view
type dont iota_view<int>{0, 42}
les itérateurs sont sur un ensemble de valeurs qui ne sont pas soumises à la destruction, car elles sont générées à la demande.
Si une fonction d’algorithme est passée à une plage dont les itérateurs dépendent de sa durée de vie, ranges::dangling
est retournée au lieu d’une sous-plage afin que l’utilisation incorrecte potentielle soit détectée au moment de la compilation.
Exemple : borrowed_subrange_t
L’exemple suivant montre comment borrowed_subrange_t
détecter un itérateur dérangé, car equal_range()
et max_element
utiliser cet alias de modèle pour déterminer le type de retour :
// 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 une fonction d’algorithme qui retourne un itérateur ou un subrange
est appelé avec un argument rvalue range
, la durée de vie de l’argument de plage peut se terminer après l’appel. Cela signifie que l’itérateur retourné ou subrange
peut faire référence à des éléments dont les durées de vie ont pris fin. L’utilisation d’un itérateur anangling ou subrange
entraîne un comportement non défini.
Si une fonction d’algorithme est passée à une plage dont les itérateurs dépendent de sa durée de vie, ranges::dangling
est retournée au lieu d’un itérateur ou d’une sous-plage afin que l’utilisation incorrecte potentielle soit détectée au moment de la compilation.
1) constexpr dangling() noexcept = default;
2) template<class... Args>
constexpr dangling(Args&&...) noexcept {}
Paramètres
Args
Nombre variable de non-typesvoid
. Ils n’ont aucun effet. Les arguments sont pratiques afin que vous n’ayez pas besoin de chemins de code différents pour gérer la construction du type d’itérateur par rapport au dangling
type. Cela est utile lorsque la valeur passée indique qu’elle dangling
doit être retournée au lieu d’un itérateur.
Exemple : dangling
L’exemple suivant montre comment max_element
détecter un itérateur dérangé.
// 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
Cet alias de modèle retourne le type d’itérateur utilisé pour itérer sur le type de plage fourni.
template<class T>
using iterator_t = decltype(ranges::begin(declval<T&>()));
Paramètres
T
Type de plage pour lequel obtenir le type d’itérateur.
Exemple : iterator_t
L’exemple suivant montre comment iterator_t
être utilisé pour déclarer un itérateur pour un vecteur :
// 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
Retourne le type de différence pour l’itérateur de la plage spécifiée.
template<range R>
using range_difference_t = iter_difference_t<iterator_t<R>>;
Paramètres
R
Plage dont l’itérateur fournit le type de différence.
Exemple : range_difference_t
L’exemple suivant montre comment range_difference_t
utiliser la distance entre les éléments d’une plage :
// 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
Retourne le type de référence de l’itérateur de la plage spécifiée. En d’autres termes, le type de référence des éléments de la plage.
template <range R>
using range_reference_t = iter_reference_t<ranges::iterator_t<R>>;
Paramètres
R
Plage pour laquelle le type de référence de son type itérateur est retourné.
Exemple : range_reference_t
L’exemple suivant montre range_reference_t
comment faire référence au type des éléments d’une plage :
// 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
Retourne le type de référence rvalue pour l’itérateur de la plage spécifiée. En d’autres termes, le type de référence rvalue des éléments de la plage.
template <range R>
using range_rvalue_reference_t = iter_reference_t<ranges::iterator_t<R>>;
Paramètres
R
Plage permettant d’obtenir le type de référence rvalue à son type d’itérateur.
Exemple : range_rvalue_reference_t
L’exemple suivant montre range_rvalue_reference_t
comment faire référence à un type rvalue des éléments d’une plage :
// 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
Retourne le type de la size
fonction pour l’objet spécifié sized_range
.
template <range R>
using range_size_t = iter_reference_t<ranges::iterator_t<R>>;
Paramètres
R
Plage permettant d’obtenir le type de sa size
fonction.
Exemple : range_size_t
L’exemple suivant montre range_size_t
comment faire référence au nombre d’éléments d’une plage :
// 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
Retourne le type valeur de l’itérateur de plage spécifié. En d’autres termes, le type des éléments de la plage.
template <ranges::range R>
using range_value_t = iter_value_t<ranges::iterator_t<R>>;
Paramètres
R
Plage permettant d’obtenir le type valeur de son itérateur.
Exemple : range_value_t
L’exemple suivant montre comment range_value_t
faire référence au type d’éléments d’une plage :
// 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
Retourne le type sentinelle de la plage spécifiée.
template <range R>
using sentinel_t = decltype(ranges::end(declval<R&>()));
Paramètres
R
Plage pour laquelle obtenir le type sentinelle.
Exemple : sentinel_t
L’exemple suivant montre comment sentinel_t
déterminer si le type d’itérateur et le type sentinel sont les mêmes :
// 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