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
타입의 객체를 생성합니다:
C
가
input_range
를 만족하지 않거나
std::
convertible_to
<
ranges::
range_reference_t
<
R
>
,
ranges::
range_value_t
<
C
>>
가
true
인 경우:
C
의 객체를 초기화합니다. 단,
std::
constructible_from
<
C, R, Args...
>
가
true
인 경우에만 적용됩니다.
C
타입의 객체를
직접 초기화
(단 직접 목록 초기화는 제외)하는 것처럼 비-뷰 객체를 구성합니다. 단,
std::
constructible_from
<
C,
std::
from_range_t
, R, Args...
>
가
true
인 경우에만 적용됩니다.
C
타입의 객체를 반복자-감시자 쌍(
ranges::
begin
(
r
)
를 반복자로,
ranges::
end
(
r
)
를 감시자로 사용)에서 생성하며, 반복자와 감시자는 동일한 타입을 가져야 합니다(즉, 소스 범위는 공통 범위(common range)여야 합니다). 그리고 다음의 모든 조건이
true
인 경우 나머지 함수 인수
std::
forward
<
Args
>
(
args
)
...
를 사용합니다:
- 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
타입의 요소 하나가 멤버 함수 호출
emplace_back
,
push_back
,
emplace
또는
insert
를 통해
Container
에 추가될 수 있으면
true
입니다.
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> #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::to<std::vector>(); static_assert(std::same_as<decltype(vec), std::vector<int>>); std::println("{}", vec); auto list = vec | std::views::take(3) | std::ranges::to<std::list<double>>(); std::println("{}", list); } void ctor_demos() { // 1.a.1) 직접 초기화 { char array[]{'a', 'b', '\0', 'c'}; // 인수 유형이 결과 값 유형으로 변환 가능한 경우: auto str_to = std::ranges::to<std::string>(array); // Equivalent to std::string str(array); // 결과 타입은 입력 범위가 아닙니다: auto re_to = std::ranges::to<std::regex>(array); // Equivalent to std::regex re(array); } // 1.a.2) from_range 생성자 { auto list = {'a', 'b', '\0', 'c'}; // 인수 타입이 결과 값 타입으로 변환 가능한 경우: auto str_to = std::ranges::to<std::string>(list); // Equivalent to // std::string str(std::from_range, list); // 결과 타입은 입력 범위가 아닙니다: [[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'}; // 인수 타입이 결과 값 타입으로 변환 가능한 경우: auto devector_to = std::ranges::to<boost::컨테이너::devector<char>>(list); // Equivalent to boost::컨테이너::devector<char> devector(std::ranges::begin(list), std::ranges::end(list)); // 결과 타입은 입력 범위가 아닙니다: 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); } }
출력:
[2, 4, 6, 8] [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]