Udostępnij za pośrednictwem


<ranges> szablony aliasów

Szablon aliasu to alias dla innego typu, który może zwiększyć czytelny kod. Na przykład następujący alias, conditional_t, jest aliasem dla elementu borrowed_range lub dangling zakresu, w zależności od rodzaju przekazanego range elementu:

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

Aby uzyskać więcej informacji na temat szablonów aliasów, zobacz Aliasy i definicje typów.

Nagłówek <algorithm> definiuje następujące szablony aliasów, które określają typy iteratorów i sentinels dla elementu range:

Szablon aliasu opis
borrowed_iterator_tC++20 Ustal, czy iterator zwrócił odwołanie range do zakresu, którego okres istnienia zakończył się.
borrowed_subrange_tC++20 Ustal, czy zwrócony subrange dla elementu range odnosi się do zakresu, którego okres istnienia zakończył się.
danglingC++20 Wskazuje, że zwrócony iterator range/subrange cyklu życia range/subrange odwołuje się do niego.
iterator_tC++20 Zwraca typ iteratora dla określonego zakresu.
range_difference_tC++20 Zwraca typ różnicy dla iteratora określonego zakresu.
range_reference_tC++20 Zwraca typ odwołania dla iteratora określonego zakresu.
range_rvalue_reference_tC++20 Zwraca typ odwołania rvalue dla iteratora określonego zakresu. Innymi słowy, typ odwołania rvalue elementów zakresu.
range_size_tC++20 Zwraca typ używany do zgłaszania sizeokreślonego zakresu .
range_value_tC++20 Zwraca typ wartości iteratora określonego zakresu. Innymi słowy, typ elementów w zakresie.
sentinel_tC++20 Zwraca typ sentinel dla określonego zakresu.

borrowed_iterator_t

Gdy funkcja algorytmu zwracająca iterator jest wywoływana z argumentem rvalue range , okres istnienia zakresu może zakończyć się po wywołaniu. Oznacza to, że zwrócony iterator może odwoływać się do elementów, których okresy istnienia zakończyły się. Użycie iteratora zwisającego powoduje niezdefiniowane zachowanie.

Ten alias szablonu zwraca wartość ranges::dangling wskazującą, że jest to sytuacja dla danego argumentu zakresu lub std::ranges::iterator_t<R> aby wskazać, że można bezpiecznie użyć zwróconego iteratora, ponieważ zakres, który odwołuje się do modeli borrowed_range lub zakres został przekazany jako lvalue.

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

Parametry

R
Zakres do przetestowania.

Uwagi

Okres istnienia zakresu rvalue może zakończyć się po wywołaniu funkcji niezależnie od tego, czy modele borrowed_range zakresu. Jeśli jest borrowed_rangeto element , możesz nadal używać iteratorów z dobrze zdefiniowanym zachowaniem niezależnie od tego, kiedy okres istnienia zakresu kończy się.

Przypadki, w których tak nie jest, na przykład w przypadku kontenerów, takich jak vector lub list dlatego, że po zakończeniu okresu istnienia kontenera iteratory odwołują się do elementów, które zostały zniszczone.

Można nadal używać iteratorów dla borrowed_rangeobiektu , na przykład dla obiektu view iota_view<int>{0, 42} lubiego, którego iteratory są ponad zestawem wartości, które nie podlegają niszczeniu, ponieważ są generowane na żądanie.

Jeśli funkcja algorytmu jest przekazywana zakres, którego iteratory zależą od jego okresu istnienia, ranges::dangling jest zwracany zamiast iteratora lub podgrupy, więc potencjalne nieprawidłowe użycie zostanie wykryte w czasie kompilacji.

Przykład: borrowed_iterator_t

W poniższym przykładzie pokazano, jak borrowed_iterator_t wykrywa zwisający iterator. Funkcja ranges::max_element() używa tego aliasu szablonu do określenia typu zwracanego:

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

Gdy funkcja algorytmu zwracająca subrange element jest wywoływana z argumentem rvalue range , okres istnienia zakresu może zakończyć się po wywołaniu. Oznacza to, że zwrócony subrange element może odwoływać się do elementów, których okresy istnienia zakończyły się. Użycie zwisającego subrange zachowania powoduje niezdefiniowane zachowanie.

Ten alias szablonu zwraca wartość ranges::dangling , aby wskazać, że może to być sytuacja dla danego argumentu zakresu lub subrange<ranges::iterator_t<R>> aby wskazać, że można bezpiecznie użyć zwróconego podrozmieszczenia, ponieważ albo zakres, którego elementy odnoszą się do modeli borrowed_range , lub zakres został przekazany jako lvalue.

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

Parametry

R
Zakres do przetestowania.

Uwagi

Okres istnienia zakresu rvalue może zakończyć się po wywołaniu funkcji niezależnie od tego, czy modele borrowed_range zakresu. Jeśli jest borrowed_rangeto element , możesz nadal używać iteratorów z dobrze zdefiniowanym zachowaniem niezależnie od tego, kiedy okres istnienia zakresu kończy się.

Przypadki, w których tak nie jest, na przykład w przypadku kontenerów, takich jak vector lub list dlatego, że po zakończeniu okresu istnienia kontenera iteratory odwołują się do elementów, które zostały zniszczone.

Można nadal używać iteratorów dla borrowed_rangeobiektu , na przykład dla obiektu view iota_view<int>{0, 42} lubiego, którego iteratory są ponad zestawem wartości, które nie podlegają niszczeniu, ponieważ są generowane na żądanie.

Jeśli funkcja algorytmu jest przekazywana zakres, którego iteratory zależą od jego okresu istnienia, jest zwracany zamiast podgrupy, ranges::dangling tak aby w czasie kompilacji wykryto potencjalne nieprawidłowe użycie.

Przykład: borrowed_subrange_t

W poniższym przykładzie pokazano, jak borrowed_subrange_t wykrywa iterator zwisujący, ponieważ equal_range() i max_element użyj tego aliasu szablonu do określenia typu zwracanego:

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

Jeśli funkcja algorytmu zwracająca iterator lub subrange element jest wywoływana z argumentem rvalue range , okres istnienia argumentu zakresu może zakończyć się po wywołaniu. Oznacza to, że zwrócony iterator lub subrange może odwoływać się do elementów, których okresy istnienia zakończyły się. Użycie iteratora zwisającego lub subrange powoduje niezdefiniowane zachowanie.

Jeśli funkcja algorytmu jest przekazywana zakres, którego iteratory zależą od jego okresu istnienia, ranges::dangling jest zwracany zamiast iteratora lub podrange, aby potencjalne nieprawidłowe użycie zostało wykryte w czasie kompilacji.

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

Parametry

Args
Zmienna liczba typów innychvoid niż. Nie mają żadnego efektu. Argumenty są wygodą, dzięki czemu nie potrzebujesz różnych ścieżek kodu do obsługi konstruowania typu iteratora w porównaniu z typem dangling . Jest to przydatne, gdy przekazana wartość wskazuje, że dangling powinna zostać zwrócona zamiast iteratora.

Przykład: dangling

W poniższym przykładzie pokazano, jak max_element wykrywa zwisający iterator.

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

Ten alias szablonu zwraca typ iteratora używany do iterowania w podanym typie zakresu.

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

Parametry

T
Typ zakresu, dla który ma uzyskać typ iteratora.

Przykład: iterator_t

W poniższym przykładzie pokazano, jak iterator_t można użyć do deklarowania iteratora dla wektora:

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

Zwraca typ różnicy dla iteratora określonego zakresu.

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

Parametry

R
Zakres, którego iterator zapewni typ różnicy.

Przykład: range_difference_t

W poniższym przykładzie pokazano, jak range_difference_t jest używana do przechowywania odległości między elementami w zakresie:

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

Zwraca typ odwołania dla iteratora określonego zakresu. Innymi słowy, typ odwołania elementów zakresu.

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

Parametry

R
Zakres, dla którego zwracany jest typ odwołania typu iteratora.

Przykład: range_reference_t

W poniższym przykładzie pokazano range_reference_t odwołanie do typu elementów w zakresie:

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

Zwraca typ odwołania rvalue dla iteratora określonego zakresu. Innymi słowy, typ odwołania rvalue elementów zakresu.

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

Parametry

R
Zakres umożliwiający pobranie typu odwołania rvalue do typu iteratora.

Przykład: range_rvalue_reference_t

W poniższym przykładzie pokazano range_rvalue_reference_t odwołanie do typu rvalue elementów w zakresie:

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

Zwraca typ size funkcji dla określonego sized_rangeelementu .

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

Parametry

R
Zakres umożliwiający uzyskanie typu jego size funkcji.

Przykład: range_size_t

Poniższy przykład przedstawia range_size_t odwołanie do liczby elementów w zakresie:

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

Zwraca typ wartości iteratora określonego zakresu. Innymi słowy, typ elementów w zakresie.

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

Parametry

R
Zakres umożliwiający uzyskanie typu wartości iteratora.

Przykład: range_value_t

W poniższym przykładzie pokazano, jak range_value_t odnosi się do typu elementów w zakresie:

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

Zwraca typ sentinel dla określonego zakresu.

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

Parametry

R
Zakres umożliwiający uzyskanie typu sentinel.

Przykład: sentinel_t

W poniższym przykładzie pokazano użycie metody sentinel_t w celu określenia, czy typ iteratora i typ sentinel są takie same:

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

Zobacz też

<ranges>
Adaptery zakresowe
Klasy widoków