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型のオブジェクトを直接初期化(ただし直接リスト初期化ではない)するかのように非ビューオブジェクトを構築します。C型のオブジェクトを直接初期化(ただし直接リスト初期化ではない)するかのように非ビューオブジェクトを構築します。C型のオブジェクトを直接初期化(ただし直接リスト初期化ではない)するかのように非ビューオブジェクトを構築します。- 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 /*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型の1つの要素が、メンバ関数呼び出し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<std::decay_t<Args>...>(std::forward<Args>(args)...)で構築されたstd::tupleオブジェクトtupを持っているかのように振る舞います。ただし、返されるオブジェクトの代入動作は未指定であり、名前は説明専用です。
コンストラクタ
ranges::to(3,4)の戻り値の型は、そのコピー/ムーブコンストラクタがメンバごとのコピー/ムーブを実行するかのように振る舞います。そのすべてのメンバオブジェクト(上記で指定)がCopyConstructibleであればCopyConstructibleであり、そうでなければMoveConstructibleです。
メンバー関数 operator()
range::to</* 以下を参照 */>(args...)の以前の呼び出しから取得されたオブジェクトGが与えられたとき、Gを指定するglvaluegが関数呼び出し式g(r)で呼び出されると、次のように格納されたオブジェクトの呼び出しが行われます。
- ranges::to</* 以下を参照 */>(r, std::get<Ns>(g.tup)...)、ここで
- rは、
input_rangeを満たさなければならないソース範囲オブジェクトです。 - Nsは、整数パック0, 1, ..., (sizeof...(Args) - 1)です。
- gが呼び出し式でlvalueであればlvalueであり、そうでなければrvalueです。したがって、g(r)がコピーするのに対して、std::move(g)(r)はバインドされた引数を呼び出しにムーブすることができます。
- 指定されたテンプレート引数は、(3)
Cまたは(4)クラステンプレートCから推論された型で、viewを満たしてはなりません。
- rは、
gがvolatile修飾された型を持つ場合、プログラムは不適格です。
[編集] 例外
非ビューオブジェクトの構築が例外をスローする場合にのみ例外をスローします。
[編集] 注釈
間接呼び出し中にlvalue参照が生成されるため、要素のコンテナへの挿入にはコピーが含まれる可能性があり、ムーブよりも効率が悪い場合があります。ユーザーは、間接呼び出し中に要素が常にrvalue参照を生成し、ムーブを意味するように、views::as_rvalueを使用して範囲を適応させることを選択できます。
パイプ構文を使用する場合、丸括弧は必須です。
auto vec = r | std::ranges::to<std::vector>; // Error auto vec = r | std::ranges::to<std::vector>(); // OK
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_lib_ranges_to_container |
202202L |
(C++23) | 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) 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); } }
出力
[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]