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 /*range adaptor closure*/ 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
のオブジェクトを
直接初期化
(ただし直接リスト初期化ではない)するかのように行う。ここでイテレータとセンチネルは同じ型を持つ(つまり、ソース範囲は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
のオブジェクトを
直接初期化
(ただし直接リスト初期化ではない)するかのように構築し、その後以下の等価な呼び出しを実行する:
|
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 < 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
の場合、範囲内でのネストした範囲構築を可能にします。
/*input-iterator*/ を、以下の要件を満たす説明専用の型とする: LegacyInputIterator :
|
struct
/*入力イテレータ*/
{
|
( 説明専用* ) | |
Let /*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修飾されていないクラス型でなければならない
(
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
が与えられたとき、
G
を指定する左辺値
g
が関数呼び出し式
g
(
r
)
で呼び出されると、格納されたオブジェクトの呼び出しが発生する。これは以下のように実行される:
- ranges :: to < /* see below */ > ( r, std :: get < Ns > ( g. tup ) ... ) 、ここで
-
-
r
は
input_rangeを満たす必要があるソースレンジオブジェクトである。 - Ns は整数パック 0 , 1 , ..., ( sizeof... ( Args ) - 1 ) である。
- g は、呼び出し式で左辺値である場合は左辺値として、それ以外の場合は右辺値として扱われる。したがって std :: move ( g ) ( r ) はバインドされた引数を呼び出しにムーブできるが、 g ( r ) はコピーする。
-
指定されたテンプレート引数は
(
3
)
Cまたは ( 4 )viewを満たさないクラステンプレートCから推論された型である。
-
r
は
g がvolatile修飾型を持つ場合、プログラムは不適格である。
例外
ビュー以外のオブジェクトの構築が例外を送出する場合にのみ例外を送出します。
注記
コンテナへの要素の挿入はコピーが関与する可能性があり、間接参照呼び出し中に左辺値参照が生成されるため、ムーブよりも効率が低下することがあります。ユーザーは views:: as_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
および
変更
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); // 次と同等 std::string str(array); // 結果の型は入力範囲ではありません: auto re_to = std::ranges::to<std::regex>(array); // 次と同等 std::regex re(array); } // 1.a.2) from_range コンストラクタ { auto list = {'a', 'b', '\0', 'c'}; // 引数の型は結果値の型に変換可能: auto str_to = std::ranges::to<std::string>(list); // 次と同等 // std::string str(std::from_range, list); // 結果の型は入力範囲ではありません: [[maybe_unused] (注:元のテキストは閉じ括弧のみのため、日本語でも同じ記号を保持します)] auto pair_to = std::ranges::to<std::pair<std::from_range_t, bool>>(true); // 次と同等 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); // 次と同等 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); // 次と同等 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]