Namespaces
Variants

std::ranges:: to

From cppreference.net
Ranges library
Range adaptors
(注:このHTML要素には翻訳対象のテキストコンテンツが含まれていないため、元の構造を保持したまま出力します)
定義於標頭檔 <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 タグ付き範囲コンストラクタ、イテレータ-番兵ペアを受け取るコンストラクタを呼び出すか、またはソース範囲の各要素を引数で構築されたオブジェクトにバック挿入することによって、新しい非ビューオブジェクトを構築します。

1) 以下の方法で r の要素から型 C のオブジェクトを構築します:
a) もし C input_range を満たさない、または std:: convertible_to < ranges:: range_reference_t < R > , ranges:: range_value_t < C >> true の場合:
1) 非ビューオブジェクトを、 direct-initializing (ただしdirect-list-initializingではない)ように構築する。 ソース範囲 std:: forward < R > ( r ) および残りの関数引数 std:: forward < Args > ( args ) ... から型 C のオブジェクトを構築する。ただし、 std:: constructible_from < C, R, Args... > true の場合に限る。
2) それ以外の場合、非ビューオブジェクトを構築する。これは、追加の曖昧性解消タグ std:: from_range 、ソース範囲 std:: forward < R > ( r ) 、および残りの関数引数 std:: forward < Args > ( args ) ... から型 C のオブジェクトを 直接初期化 (ただし直接リスト初期化は除く)するかのように行う。ただし、これは std:: constructible_from < C, std:: from_range_t , R, Args... > true の場合に限る。
3) それ以外の場合、非ビューオブジェクトを構築する。これは、イテレータ-センチネルペア( ranges:: begin ( r ) をイテレータとして、 ranges:: end ( r ) をセンチネルとして)から型 C のオブジェクトを 直接初期化 (ただし直接リスト初期化ではない)するかのように行う。ここでイテレータとセンチネルは同じ型を持つ(つまり、ソース範囲はcommon rangeでなければならない)。また、以下の条件がすべて true である場合、残りの関数引数 std:: forward < Args > ( args ) ... を渡す:
4) それ以外の場合、非ビューの範囲オブジェクトを、残りの関数引数から型 C のオブジェクトを 直接初期化 (ただし直接リスト初期化ではない)するかのように構築し、その後以下の等価な呼び出しを実行する:

if constexpr ( ranges:: sized_range < R > && /*reservable-container*/ < C > )
c. reserve ( static_cast < ranges:: range_size_t < C >> ( ranges:: size ( r ) ) ) ;
ranges:: for_each ( r, /*container-appender*/ ( c ) ) ;

(C++26まで)

if constexpr ( ranges :: approximately_sized_range < R >
&& /*reservable-container*/ < C > )
c. reserve ( static_cast < ranges:: range_size_t < C >> ( ranges :: reserve_hint ( r ) ) ) ;
ranges:: for_each ( r, /*container-appender*/ ( c ) ) ;

(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 の場合に有効である:

b) それ以外の場合、戻り値の式は以下と等価です:

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 の場合、範囲内でのネストした範囲構築を可能にします。

それ以外の場合、プログラムは不適格です。
2) Constructs an object of deduced type from the elements of r .

/*input-iterator*/ を、以下の要件を満たす説明専用の型とする: LegacyInputIterator

struct /*入力イテレータ*/

{
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 ; // 定義されていない
pointer operator - > ( ) const ; // 定義されていない
/*入力イテレータ*/ & operator ++ ( ) ; // 定義されていない
/*入力イテレータ*/ operator ++ ( int ) ; // 定義されていない
bool operator == ( const /*入力イテレータ*/ & ) const ; // 定義されていない

} ;
( 説明専用* )

Let /*DEDUCE-EXPR*/ を次のように定義する:

The call is equivalent to to < decltype ( /*DEDUCE-EXPR*/ ) >
( std:: forward < R > ( r ) , std:: forward < Args > ( args ) ... )
.
3,4) 完全転送呼び出しラッパーを返します。これはまた RangeAdaptorClosureObject でもあります。
5) これは true ranges:: sized_range を満たし、予約可能な条件を備えている場合に設定されます。
6) Reference 型の要素がメンバ関数呼び出し emplace_back push_back emplace または insert を通じて Container に追加可能な場合 true となります。
7) コンテナに1つの要素を追加する呼び出しが式等価となる関数オブジェクトを返します。返される式は以下と等価です:

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 ) ) ;
} ;

8) コンテナの定義において、入力範囲 R の構築に使用され、その範囲参照型は T に変換可能でなければならない。

目次

パラメータ

r - ソース範囲オブジェクト
args - 範囲を構築するための引数リスト ( 1,2 ) または範囲アダプタクロージャオブジェクトの最後のパラメータにバインドする引数リスト ( 3,4 )
型要件
-
C はCV修飾されていないクラス型でなければならない ( 1,3 )

戻り値

1,2) 構築された非ビューオブジェクト。
3,4) 指定されていない型のレンジアダプタクロージャオブジェクトで、以下の特性を持つ:

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 から推論された型である。

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]