<ranges>
Шаблоны псевдонимов
Шаблон псевдонима — это псевдоним другого типа, который может сделать код более читаемым. Например, следующий псевдоним , является псевдонимом conditional_t
для любого borrowed_range
или dangling
диапазона в зависимости от типа range
переданного в:
// 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
}
Дополнительные сведения о шаблонах псевдонимов см. в разделе "Псевдонимы" и "Typedefs".
Заголовок <algorithm>
определяет следующие шаблоны псевдонимов, определяющие типы итераторов и sentinels для range
:
Шаблон псевдонима | Description |
---|---|
borrowed_iterator_t C++20 |
Определите, возвращается ли итератор для range диапазона, время существования которого завершено. |
borrowed_subrange_t C++20 |
Определите, возвращается ли возвращаемый subrange диапазон range , время существования которого завершилось. |
dangling C++20 |
Указывает, что возвращаемый итератор извеченного времени существования/subrange range ссылки на него.range /subrange |
iterator_t C++20 |
Возвращает тип итератора для указанного диапазона. |
range_difference_t C++20 |
Возвращает тип разницы для итератора указанного диапазона. |
range_reference_t C++20 |
Возвращает ссылочный тип для итератора указанного диапазона. |
range_rvalue_reference_t C++20 |
Возвращает ссылочный тип rvalue для итератора указанного диапазона. Другими словами, ссылочный тип rvalue элементов диапазона. |
range_size_t C++20 |
Возвращает тип, используемый для отправки отчета о заданном диапазоне size . |
range_value_t C++20 |
Возвращает тип значения итератора указанного диапазона. Или другими словами, тип элементов в диапазоне. |
sentinel_t C++20 |
Возвращает тип sentinel для указанного диапазона. |
borrowed_iterator_t
Если функция алгоритма, возвращающая итератор, вызывается с аргументом rvalue range
, время существования диапазона может завершиться после вызова. Это означает, что возвращаемый итератор может ссылаться на элементы, время существования которых завершилось. Использование дальнего итератора приводит к неопределенному поведению.
Этот псевдоним шаблона возвращается ranges::dangling
, чтобы указать, что это ситуация для заданного аргумента диапазона или std::ranges::iterator_t<R>
чтобы указать, что он безопасно использовать возвращаемый итератор, так как диапазон, который он относится к моделям borrowed_range
или диапазон был передан как lvalue.
template<ranges::range R>
using borrowed_iterator_t = conditional_t<ranges::borrowed_range<R>,
ranges::iterator_t<R>, ranges::dangling>;
Параметры
R
Диапазон для тестирования.
Замечания
Время существования диапазона rvalue может завершиться после вызова функции, независимо от того borrowed_range
, модели диапазона или нет. Если это borrowed_range
так, вы можете продолжать использовать итераторы с хорошо определенным поведением независимо от того, когда время существования диапазона заканчивается.
В случаях, когда это не так, например для контейнеров, таких vector
как или list
из-за окончания времени существования контейнера, итераторы будут ссылаться на элементы, которые были уничтожены.
Вы можете продолжать использовать итераторы для borrowed_range
например, например, например, для view
iota_view<int>{0, 42}
того, чьи итераторы имеют набор значений, которые не подвергаются уничтожению, так как они создаются по требованию.
Если функция алгоритма передает диапазон, итераторы которого зависят от его времени существования, ranges::dangling
возвращается вместо итератора или подранга, поэтому потенциальное неправильное использование обнаруживается во время компиляции.
Пример: borrowed_iterator_t
В следующем примере показано, как borrowed_iterator_t
обнаружить итератор дальнего итератора. ranges::max_element()
Функция использует этот псевдоним шаблона для определения типа возвращаемого значения:
// 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
Когда функция алгоритма, возвращающая subrange
вызов с аргументом rvalue range
, время существования диапазона может завершиться после вызова. Это означает, что возвращаемый subrange
объект может ссылаться на элементы, время существования которых завершилось. Использование дальнего subrange
поведения приводит к неопределенному поведению.
Этот псевдоним шаблона либо возвращается ranges::dangling
, чтобы указать, что это может быть ситуация для заданного аргумента диапазона, либо subrange<ranges::iterator_t<R>>
чтобы указать, что он безопасно использовать возвращаемый подранг, так как либо диапазон, элементы которого относятся к моделям borrowed_range
, либо диапазон был передан как lvalue.
template<ranges::range R>
using borrowed_subrange_t = conditional_t<ranges::borrowed_range<R>,
ranges::subrange<ranges::iterator_t<R>>, ranges::dangling>;
Параметры
R
Диапазон для тестирования.
Замечания
Время существования диапазона rvalue может завершиться после вызова функции, независимо от того borrowed_range
, модели диапазона или нет. Если это borrowed_range
так, вы можете продолжать использовать итераторы с хорошо определенным поведением независимо от того, когда время существования диапазона заканчивается.
В случаях, когда это не так, например для контейнеров, таких vector
как или list
из-за окончания времени существования контейнера, итераторы будут ссылаться на элементы, которые были уничтожены.
Вы можете продолжать использовать итераторы для borrowed_range
например, например, например, для view
iota_view<int>{0, 42}
того, чьи итераторы имеют набор значений, которые не подвергаются уничтожению, так как они создаются по требованию.
Если функция алгоритма передает диапазон, итераторы которого зависят от его времени существования, возвращается вместо подранга, ranges::dangling
чтобы потенциальное неправильное использование было обнаружено во время компиляции.
Пример: borrowed_subrange_t
В следующем примере показано, как определить деангистрирующий итератор, так как borrowed_subrange_t
equal_range()
и max_element
использовать этот псевдоним шаблона для определения типа возвращаемого значения:
// 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
Если функция алгоритма, возвращающая итератор или subrange
вызывается с аргументом rvalue range
, время существования аргумента диапазона может завершиться после вызова. Это означает, что возвращаемый итератор или subrange
может ссылаться на элементы, время существования которых завершилось. Использование итератора или subrange
неопределенного поведения.
Если функция алгоритма передает диапазон, итератор которого зависит от его времени существования, возвращается вместо итератора или подранга, ranges::dangling
чтобы потенциальное неправильное использование было обнаружено во время компиляции.
1) constexpr dangling() noexcept = default;
2) template<class... Args>
constexpr dangling(Args&&...) noexcept {}
Параметры
Args
Переменное число нетиповvoid
. Они не имеют никакого эффекта. Аргументы являются удобством, поэтому для обработки создания типа dangling
итератора не требуется разные пути кода. Это полезно, если переданное значение указывает, что dangling
следует возвращать вместо итератора.
Пример: dangling
В следующем примере показано, как max_element
обнаружить итератор дальнего итератора.
// 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
Этот псевдоним шаблона возвращает тип итератора, используемый для итерации по указанному типу диапазона.
template<class T>
using iterator_t = decltype(ranges::begin(declval<T&>()));
Параметры
T
Тип диапазона для получения типа итератора.
Пример: iterator_t
В следующем примере показано, как iterator_t
можно объявить итератор для вектора:
// 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
Возвращает тип разницы для итератора указанного диапазона.
template<range R>
using range_difference_t = iter_difference_t<iterator_t<R>>;
Параметры
R
Диапазон, итератор которого предоставит тип разницы.
Пример: range_difference_t
В следующем примере показано, как range_difference_t
использовать для хранения расстояния между элементами в диапазоне:
// 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
Возвращает ссылочный тип для итератора указанного диапазона. Другими словами, ссылочный тип элементов диапазона.
template <range R>
using range_reference_t = iter_reference_t<ranges::iterator_t<R>>;
Параметры
R
Диапазон, для которого возвращается ссылочный тип своего итератора.
Пример: range_reference_t
В следующем примере показано range_reference_t
, как ссылаться на тип элементов в диапазоне:
// 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
Возвращает ссылочный тип rvalue для итератора указанного диапазона. Другими словами, ссылочный тип rvalue элементов диапазона.
template <range R>
using range_rvalue_reference_t = iter_reference_t<ranges::iterator_t<R>>;
Параметры
R
Диапазон для получения ссылочного типа rvalue к типу итератора.
Пример: range_rvalue_reference_t
В следующем примере показано range_rvalue_reference_t
, как ссылаться на тип rvalue элементов в диапазоне:
// 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
Возвращает тип size
функции для указанного sized_range
.
template <range R>
using range_size_t = iter_reference_t<ranges::iterator_t<R>>;
Параметры
R
Диапазон для получения типа его size
функции.
Пример: range_size_t
В следующем примере показано range_size_t
число элементов в диапазоне:
// 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
Возвращает тип значения итератора указанного диапазона. Или другими словами, тип элементов в диапазоне.
template <ranges::range R>
using range_value_t = iter_value_t<ranges::iterator_t<R>>;
Параметры
R
Диапазон для получения типа значения своего итератора.
Пример: range_value_t
В следующем примере показано, как range_value_t
относится к типу элементов в диапазоне:
// 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
Возвращает тип sentinel для указанного диапазона.
template <range R>
using sentinel_t = decltype(ranges::end(declval<R&>()));
Параметры
R
Диапазон для получения типа sentinel для.
Пример: sentinel_t
В следующем примере показано использование для sentinel_t
определения того, совпадают ли тип итератора и тип sentinel:
// 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