std::ranges:: to
|
Определено в заголовочном файле
<ranges>
|
||
|
template
<
class
C,
ranges::
input_range
R,
class
...
Args
>
requires
(
!
ranges::
view
<
C
>
)
|
(1) | (начиная с C++23) |
|
template
<
template
<
class
...
>
class
C,
ranges::
input_range
R,
class
...
Args
>
|
(2) | (начиная с C++23) |
|
template
<
class
C,
class
...
Args
>
requires
(
!
ranges::
view
<
C
>
)
|
(3) | (начиная с C++23) |
|
template
<
template
<
class
...
>
class
C,
class
...
Args
>
constexpr /*адаптор диапазона-замыкание*/ to ( Args && ... args ) ; |
(4) | (начиная с C++23) |
|
Вспомогательные шаблоны
|
||
|
template
<
class
Container
>
constexpr
bool
/*reservable-container*/
=
|
(5) | ( только для демонстрации* ) |
|
template
<
class
Container,
class
Reference
>
constexpr
bool
/*container-appendable*/
=
|
(6) | ( только для демонстрации* ) |
|
template
<
class
Reference,
class
C
>
constexpr auto /*container-appender*/ ( C & c ) ; |
(7) | ( только для демонстрации* ) |
|
template
<
class
R,
class
T
>
concept
/*container-compatible-range*/
=
|
(8) | ( только для демонстрации* ) |
Перегрузки функции преобразования диапазона создают новый объект, не являющийся представлением, из исходного диапазона в качестве первого аргумента, вызывая конструктор, принимающий диапазон,
std::from_range_t
тегированный конструктор диапазона, конструктор, принимающий пару итератор-страж, или путем обратной вставки каждого элемента исходного диапазона в объект, сконструированный из аргументов.
C
из элементов
r
следующим образом:
C
не удовлетворяет
input_range
или
std::
convertible_to
<
ranges::
range_reference_t
<
R
>
,
ranges::
range_value_t
<
C
>>
является
true
:
C
из исходного диапазона
std::
forward
<
R
>
(
r
)
и остальных функциональных аргументов
std::
forward
<
Args
>
(
args
)
...
если
std::
constructible_from
<
C, R, Args...
>
равно
true
.
C
из дополнительного тега разрешения неоднозначности
std::
from_range
, исходного диапазона
std::
forward
<
R
>
(
r
)
и остальных функциональных аргументов
std::
forward
<
Args
>
(
args
)
...
если
std::
constructible_from
<
C,
std::
from_range_t
, R, Args...
>
равно
true
.
C
из пары итератор-страж (
ranges::
begin
(
r
)
в качестве итератора и
ranges::
end
(
r
)
в качестве стража, где итератор и страж имеют одинаковый тип. Другими словами, исходный диапазон должен быть общим диапазоном), и остальных аргументов функции
std::
forward
<
Args
>
(
args
)
...
если все следующие условия
true
:
- ranges:: common_range < R >
- Если std:: iterator_traits < ranges:: iterator_t < R >> :: iterator_category является валидным и обозначает тип, который удовлетворяет std:: derived_from < std:: input_iterator_tag >
- std:: constructible_from < C, ranges:: iterator_t < R > , ranges:: sentinel_t < R > , Args... >
C
из остальных аргументов функции
std::
forward
<
Args
>
(
args
)
...
со следующим эквивалентным вызовом после создания:
|
if
constexpr
(
ranges::
sized_range
<
R
>
&&
/*reservable-container*/
<
C
>
)
|
(до C++26) |
|
if
constexpr
(
ranges
::
approximately_sized_range
<
R
>
|
(начиная с C++26) |
Если
R
удовлетворяет
sized_range
(до C++26)
approximately_sized_range
(начиная с C++26)
и
C
удовлетворяет
reservable-container
, созданный объект
c
типа
C
может зарезервировать память с начальным размером хранилища
ranges::
size
(
r
)
(до C++26)
ranges
::
reserve_hint
(
r
)
(начиная с C++26)
для предотвращения дополнительных выделений памяти при вставке новых элементов. Каждый элемент
r
добавляется в
c
.
Вышеуказанные операции допустимы, если оба следующих условия true :
- std:: constructible_from < Args... >
-
container-appendable< C, ranges:: range_reference_t < R >>
to
<
C
>
(
ranges::
ref_view
(
r
)
|
views::
transform
(
[
]
(
auto
&&
elem
)
{
return
to
<
ranges::
range_value_t
<
C
>>
(
std::
forward
<
decltype
(
elem
)
>
(
elem
)
)
;
}
)
,
std::
forward
<
Args
>
(
args
)
...
)
Что позволяет вложенные построения диапазонов внутри диапазона, если
ranges::
input_range
<
ranges::
range_reference_t
<
C
>>
равно
true
.
Пусть /*input-iterator*/ будет экспозиционным типом, который удовлетворяет требованиям LegacyInputIterator :
|
struct
/*input-iterator*/
{
|
( только для демонстрации* ) | |
Пусть /*DEDUCE-EXPR*/ определяется следующим образом:
- C ( std:: declval < R > ( ) , std:: declval < Args > ( ) ... ) , если это выражение корректно.
-
В противном случае,
C
(
std::
from_range
,
std::
declval
<
R
>
(
)
,
std:: declval < Args > ( ) ... ) , если это выражение корректно. -
В противном случае,
C
(
std::
declval
<
/*input-iterator*/
>
(
)
,
std:: declval < /*input-iterator*/ > ( ) ,
std:: declval < Args > ( ) ... ) , если это выражение корректно. - В противном случае программа является некорректной.
( std:: forward < R > ( r ) , std:: forward < Args > ( args ) ... ) .
Reference
может быть добавлен в
Container
через вызов функции-члена
emplace_back
,
push_back
,
emplace
или
insert
.
return
[
&
c
]
<
class
Reference
>
(
Reference
&&
ref
)
{
if
constexpr
(
requires
{
c.
emplace_back
(
std::
declval
<
Reference
>
(
)
)
;
}
)
c.
emplace_back
(
std::
forward
<
Reference
>
(
ref
)
)
;
else
if
constexpr
(
requires
{
c.
push_back
(
std::
declval
<
Reference
>
(
)
)
;
}
)
c.
push_back
(
std::
forward
<
Reference
>
(
ref
)
)
;
else
if
constexpr
(
requires
{
c.
emplace
(
c.
end
(
)
,
std::
declval
<
Reference
>
(
)
)
;
}
)
c.
emplace
(
c.
end
(
)
,
std::
forward
<
Reference
>
(
ref
)
)
;
else
c.
insert
(
c.
end
(
)
,
std::
forward
<
Reference
>
(
ref
)
)
;
}
;
R
, тип ссылки диапазона которого должен быть конвертируем в
T
.
Содержание |
Параметры
| r | - | объект исходного диапазона |
| args | - | список аргументов для ( 1,2 ) конструирования диапазона или ( 3,4 ) привязки к последним параметрам объекта замыкания адаптера диапазона |
| Требования к типам | ||
-
C
должен быть типом класса без cv-квалификаторов
(
1,3
)
|
||
Возвращаемое значение
ranges::to тип возвращаемого значения
Объекты-члены
Возвращаемый объект ведет себя так, как если бы у него нет целевого объекта, и объект std::tuple tup созданный с помощью std:: tuple < std:: decay_t < Args > ... > ( std:: forward < Args > ( args ) ... ) , за исключением того, что поведение присваивания возвращаемого объекта не определено, а имена используются только для демонстрации.
Конструкторы
Тип возвращаемого значения
ranges::to
(
3,4
)
ведет себя так, как если бы его конструкторы копирования/перемещения выполняют почленное копирование/перемещение. Он является
CopyConstructible
если все его объекты-члены (указанные выше) являются
CopyConstructible
, и является
MoveConstructible
в противном случае.
Функция-член
operator()
Для объекта
G
полученного из предыдущего вызова
range
::
to
<
/* see below */
>
(
args...
)
, когда glvalue
g
обозначающий
G
вызывается в выражении вызова функции
g
(
r
)
, происходит вызов сохраненного объекта, как если бы с помощью
- ranges :: to < /* see below */ > ( r, std :: get < Ns > ( g. tup ) ... ) , где
-
-
r
является объектом исходного диапазона, который должен удовлетворять
input_range. - Ns является целочисленным пакетом 0 , 1 , ..., ( sizeof... ( Args ) - 1 ) .
- g является lvalue в выражении вызова, если он является lvalue в выражении вызова, и является rvalue в противном случае. Таким образом std :: move ( g ) ( r ) может перемещать связанные аргументы в вызов, тогда как g ( r ) будет копировать.
-
Указанный аргумент шаблона это
(
3
)
Cили ( 4 ) выведенный тип из шаблона классаCкоторый не должен удовлетворятьview.
-
r
является объектом исходного диапазона, который должен удовлетворять
Программа некорректна, если g имеет тип с квалификатором volatile.
Исключения
Выбрасывает исключение только в случае, если конструкция не-view объекта выбрасывает исключение.
Примечания
Вставка элементов в контейнер может включать копирование, которое может быть менее эффективным, чем перемещение, поскольку при косвенном вызове создаются ссылки на lvalue. Пользователи могут выбрать использование views:: as_rvalue для адаптации диапазона, чтобы их элементы всегда создавали ссылку на rvalue при косвенном вызове, что подразумевает перемещение.
Скобки являются обязательными при использовании синтаксиса с вертикальной чертой.
auto vec = r | std::ranges::to<std::vector>; // Ошибка auto vec = r | std::ranges::to<std::vector>(); // OK
| Макрос тестирования возможностей | Значение | Стандарт | Функция |
|---|---|---|---|
__cpp_lib_ranges_to_container
|
202202L
|
(C++23) |
std::ranges::to
|
__cpp_lib_ranges_reserve_hint
|
202502L
|
(C++26) |
ranges::approximately_sized_range
,
ranges::reserve_hint
и
изменения
в
std::ranges::to
|
Пример
Ссылка для предварительного просмотра: Compiler Explorer
#include <boost/container/devector.hpp> #include <concepts> #include <initializer_list> #include <list> #include <print> #include <ranges> #include <regex> #include <string> #include <vector> #ifndef __cpp_lib_format_ranges #include <format> #include <sstream> auto print_aid(const auto& v) { std::ostringstream out; out << '['; for (int n{}; const auto& e : v) out << (n++ ? ", " : "") << e; out << ']'; return out; } template<typename T> struct std::formatter<std::vector<T>, char> { template<class ParseContext> constexpr ParseContext::iterator parse(ParseContext& ctx) { return ctx.begin(); } template<class FmtContext> FmtContext::iterator format(auto const& s, FmtContext& ctx) const { auto out{print_aid(s)}; return std::ranges::copy(std::move(out).str(), ctx.out()).out; } }; template<typename T> struct std::formatter<std::list<T>, char> { template<class ParseContext> constexpr ParseContext::iterator parse(ParseContext& ctx) { return ctx.begin(); } template<class FmtContext> FmtContext::iterator format(auto const& s, FmtContext& ctx) const { auto out{print_aid(s)}; return std::ranges::copy(std::move(out).str(), ctx.out()).out; } }; #endif int main() { auto vec = std::views::iota(1, 5) | std::views::transform([](int v){ return v * 2; }) | std::ranges::в<std::vector>(); static_assert(std::same_as<decltype(vec), std::vector<int>>); std::println("{}", vec); auto list = vec | std::views::take(3) | std::ranges::в<std::list<double>>(); std::println("{}", list); } void ctor_demos() { // 1.a.1) Прямая инициализация { char array[]{'a', 'b', '\0', 'c'}; // Тип аргумента конвертируем в тип результирующего значения: auto str_to = std::ranges::в<std::string>(array); // Эквивалентно std::string str(array); // Тип результата не является входным диапазоном: auto re_to = std::ranges::в<std::regex>(array); // Эквивалентно std::regex re(array); } // 1.a.2) конструктор from_range { auto list = {'a', 'b', '\0', 'c'}; // Тип аргумента конвертируем в тип результирующего значения: auto str_to = std::ranges::в<std::string>(list); // Эквивалентно // std::string str(std::from_range, list); // Тип результата не является входным диапазоном: [[maybe_unused]] auto pair_to = std::ranges::в<std::pair<std::from_range_t, bool>>(true); // Эквивалентно std::pair<std::from_range_t, bool> pair(std::from_range, true); } // 1.a.3) конструктор с парой итераторов { auto list = {'a', 'b', '\0', 'c'}; // Тип аргумента конвертируем в тип результирующего значения: auto devector_to = std::ranges::в<boost::контейнер::devector<char>>(list); // Эквивалентно boost::контейнер::devector<char> devector(std::ranges::begin(list), std::ranges::end(list)); // Тип результата не является входным диапазоном: std::regex re; auto it_to = std::ranges::в<std::cregex_iterator>(list, re); // Эквивалентно std::cregex_iterator it(std::ranges::begin(list), std::ranges::end(list), re); } }
Вывод:
[2, 4, 6, 8] [2, 4, 6]
` содержит только числовые данные и синтаксические символы 2. HTML-теги и атрибуты сохранены без изменений 3. Отсутствует текстовый контент, подлежащий переводу
Отчёты о дефектах
Следующие отчеты об изменениях в поведении, содержащие описания дефектов, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 3984 | C++23 |
вложенная ветка конструктора
ranges::to
приводила к
некорректной программе, если
R&
не моделирует
viewable_range
|
сделана корректной |
| LWG 4016 | C++23 |
ветка вставки в контейнер
ranges::to
использовала итераторы вставки
|
заменена на прямое добавление
элементов в контейнер |
Ссылки
- Стандарт C++23 (ISO/IEC 14882:2024):
-
- 26.5.7 Преобразования диапазонов [range.utility.conv]