std::ranges::to
| 헤더 <ranges>
|
||
template< class C, ranges::input_range R, class... Args >
requires (!ranges::view<C>)
constexpr C to( R&& r, Args&&... args );
|
에 정의됨 (1) | (C++23부터) |
template< template< class... > class C,
ranges::input_range R, class... Args >
constexpr auto to( R&& r, Args&&... args );
|
(2) | (C++23부터) |
template< class C, class... Args >
requires (!ranges::view<C>)
constexpr /*range adaptor closure*/ to( Args&&... args );
|
(3) | (C++23부터) |
template< template< class... > class C, class... Args >
constexpr /*range adaptor closure*/ to( Args&&... args );
|
(4) | (C++23부터) |
| 도우미 템플릿 |
||
template< class Container >
constexpr bool /*reservable-container*/ =
ranges::sized_range<Container> &&
requires (Container& c, ranges::range_size_t<Container> n)
{
c.reserve(n);
{ c.capacity() } -> std::same_as<decltype(n)>;
{ c.max_size() } -> std::same_as<decltype(n)>;
};
|
(5) | (설명 전용*) |
template< class Container, class Reference >
constexpr bool /*container-appendable*/ =
requires (Container& c, Reference&& ref)
{
requires
(
requires { c.emplace_back(std::forward<Reference>(ref)); } ||
requires { c.push_back(std::forward<Reference>(ref)); } ||
requires { c.emplace(c.end(), std::forward<Reference>(ref)); } ||
requires { c.insert(c.end(), std::forward<Reference>(ref)); }
);
};
|
(6) | (설명 전용*) |
template< class Reference, class C >
constexpr auto /*container-appender*/( C& c );
|
(7) | (설명 전용*) |
template< class R, class T >
concept /*container-compatible-range*/ =
ranges::input_range<R> &&
std::convertible_to<ranges::range_reference_t<R>, T>;
|
(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...> 타입의 객체를 생성하는 것처럼 비뷰 객체를 생성합니다.true2)C인 경우 추가적인 명확성 태그 std::from_range, 소스 범위 std::forward<R>(r) 및 나머지 함수 인자들로부터 std::forward<Args>(args)... 타입의 객체를 생성하는 것처럼 비뷰 객체를 생성합니다.std::constructible_from<C, std::from_range_t, R, Args...>3)true 그렇지 않으면, C이며 반복자와 센티넬이 동일한 타입을 가짐, 즉, 소스 범위는 common_range여야 함) 및 나머지 함수 인자들 ranges::begin(r)로부터 ranges::end(r) 타입의 객체를 생성하는 것처럼 비뷰 객체를 생성합니다:
std::forward<Args>(args)...만약 true가 유효하고 ranges::common_range<R>- 를 만족하는 타입을 나타내는 경우
std::iterator_traits<ranges::iterator_t<R>>::iterator_category4)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)...(C++26까지)
|
|
(C++26부터) |
|
|
만약 |
가
Rsized_range(C++26까지)approximately_sized_range(C++26부터)를 만족하고 가 C를 만족하면, 생성된 reservable-container 타입의 객체 c는 초기 저장소 크기 C(C++26까지)ranges::size(r)(C++26부터)ranges::reserve_hint(r)로 저장 공간을 미리 할당하여 새 요소를 삽입하는 동안 추가 할당을 방지할 수 있습니다. 의 각 요소는 r에 추가됩니다.
c위 연산들은 아래 두 조건이 모두 인 경우 유효합니다:
trueb)
std::constructible_from<C, 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
그렇지 않으면 프로그램은 ill-formed입니다.
r를 /*input-iterator*/LegacyInputIterator를 만족하는 설명 전용 타입이라고 합시다:
(
struct /*input-iterator*/
{
using iterator_category = std::input_iterator_tag;
using value_type = ranges::range_value_t<R>;
using difference_type = std::ptrdiff_t;
using pointer = std::add_pointer_t<ranges::range_reference_t<R>>;
using reference = ranges::range_reference_t<R>;
reference operator*() const; // not defined
pointer operator->() const; // not defined
/*input-iterator*/& operator++(); // not defined
/*input-iterator*/ operator++(int); // not defined
bool operator==(const /*input-iterator*/&) const; // not defined
};
|
설명 전용*) | |
를 다음과 같이 정의합시다:
/*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>()...)그렇지 않으면 프로그램은 ill-formed입니다.
- 호출은 다음과 동등합니다:
.
to<decltype(/*DEDUCE-EXPR*/)> (std::forward<R>(r), std::forward<Args>(args)...)3,4)true입니다.ranges::sized_range6)true, Reference, Container 또는 emplace_back를 통해 push_back에 추가될 수 있는 경우 emplace입니다.insert7)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-unqualified 클래스 타입이어야 함
(
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()
이전 호출
range
::
to
<
/* see below */
>
(
args...
)
로부터 얻은 객체
G
에 대해, 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 )view를 만족하지 않아야 하는 클래스 템플릿C에서 추론된 타입입니다.
-
r
는
g 가 volatile 한정 타입을 가지는 경우 프로그램의 형식이 올바르지 않습니다.
예외
비-뷰 객체의 생성이 예외를 던질 때만 예외를 던집니다.
참고 사항
컨테이너에 요소를 삽입하는 작업은 복사가 포함될 수 있으며, 이는 간접 호출 과정에서 lvalue 참조가 생성되기 때문에 이동보다 효율이 낮을 수 있습니다. 사용자는 views:: as_rvalue 를 사용하여 범위를 적응시켜 요소들이 간접 호출 과정에서 항상 rvalue 참조를 생성하도록 선택할 수 있으며, 이는 이동을 의미합니다.
파이프 구문을 사용할 때 괄호는 필수입니다.
auto vec = r | std::ranges::to<std::vector>; // 오류 auto vec = r | std::ranges::to<std::vector>(); // 정상
| 기능 테스트 매크로 | 값 | 표준 | 기능 |
|---|---|---|---|
__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
, 및
변경사항
to
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>
int main()
{
auto vec = std::views::iota(1, 5)
| std::views::transform([](int v){ return v * 2; })
| std::ranges::to<std::vector>();
static_assert(std::same_as<decltype(vec), std::vector<int>>);
std::println("1) {}", vec);
auto list = vec | std::views::take(3) | std::ranges::to<std::list<double>>();
std::println("2) {}", list);
}
void ctor_demos()
{
// 1.a.1) Direct init
{
char array[]{'a', 'b', '\0', 'c'};
// Argument type is convertible to result value type:
auto str_to = std::ranges::to<std::string>(array);
// Equivalent to
std::string str(array);
// Result type is not an input range:
auto re_to = std::ranges::to<std::regex>(array);
// Equivalent to
std::regex re(array);
}
// 1.a.2) from_range ctor
{
auto list = {'a', 'b', '\0', 'c'};
// Argument type is convertible to result value type:
auto str_to = std::ranges::to<std::string>(list);
// Equivalent to
// std::string str(std::from_range, list);
// Result type is not an input range:
[[maybe_unused]]
auto pair_to = std::ranges::to<std::pair<std::from_range_t, bool>>(true);
// Equivalent to
std::pair<std::from_range_t, bool> pair(std::from_range, true);
}
// 1.a.3) iterator pair ctor
{
auto list = {'a', 'b', '\0', 'c'};
// Argument type is convertible to result value type:
auto devector_to = std::ranges::to<boost::container::devector<char>>(list);
// Equivalent to
boost::container::devector<char> devector(std::ranges::begin(list),
std::ranges::end(list));
// Result type is not an input range:
std::regex re;
auto it_to = std::ranges::to<std::cregex_iterator>(list, re);
// Equivalent to
std::cregex_iterator it(std::ranges::begin(list), std::ranges::end(list), re);
}
}
출력:
1) [2, 4, 6, 8]
2) [2, 4, 6]
결함 보고서
다음 동작 변경 결함 보고서는 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 수정된 동작 |
|---|---|---|---|
| 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]