<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_t C++20 |
Ustal, czy iterator zwrócił odwołanie range do zakresu, którego okres istnienia zakończył się. |
borrowed_subrange_t C++20 |
Ustal, czy zwrócony subrange dla elementu range odnosi się do zakresu, którego okres istnienia zakończył się. |
dangling C++20 |
Wskazuje, że zwrócony iterator range /subrange cyklu życia range /subrange odwołuje się do niego. |
iterator_t C++20 |
Zwraca typ iteratora dla określonego zakresu. |
range_difference_t C++20 |
Zwraca typ różnicy dla iteratora określonego zakresu. |
range_reference_t C++20 |
Zwraca typ odwołania dla iteratora określonego zakresu. |
range_rvalue_reference_t C++20 |
Zwraca typ odwołania rvalue dla iteratora określonego zakresu. Innymi słowy, typ odwołania rvalue elementów zakresu. |
range_size_t C++20 |
Zwraca typ używany do zgłaszania size określonego zakresu . |
range_value_t C++20 |
Zwraca typ wartości iteratora określonego zakresu. Innymi słowy, typ elementów w zakresie. |
sentinel_t C++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_range
to 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_range
obiektu , 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_range
to 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_range
obiektu , 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_range
elementu .
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