Partager via


<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_test 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_tC++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_tC++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.
danglingC++20 Indique que l’itérateur retourné d’une durée de vie de celle-ci/subrange rangefait référence.range/subrange
iterator_tC++20 Retourne le type d’itérateur pour la plage spécifiée.
range_difference_tC++20 Retourne le type de différence pour l’itérateur de la plage spécifiée.
range_reference_tC++20 Retourne le type de référence de l’itérateur de la plage spécifiée.
range_rvalue_reference_tC++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_tC++20 Retourne le type utilisé pour signaler la plage sizespécifiée.
range_value_tC++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_tC++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

Voir aussi

<ranges>
Adaptateurs de plage
Afficher les classes