Namespaces
Variants

std::ranges:: to

From cppreference.net
Ranges library
Range adaptors
(Anmerkung: Der bereitgestellte HTML-Code enthält keinen übersetzbaren Text, da alle Tags leer sind. Die Struktur bleibt unverändert, wie angefordert.)
Definiert im Header <ranges>
template < class C, ranges:: input_range R, class ... Args >

erfordert ( ! ranges:: view < C > )

constexpr C to ( R && r, Args && ... args ) ;
(1) (seit C++23)
template < template < class ... > class C,

ranges:: input_range R, class ... Args >

constexpr auto to ( R && r, Args && ... args ) ;
(2) (seit C++23)
template < class C, class ... Args >

requires ( ! ranges:: view < C > )

constexpr /*range adaptor closure*/ to ( Args && ... args ) ;
(3) (seit C++23)
template < template < class ... > class C, class ... Args >
constexpr /*Range-Adapter-Closure*/ to ( Args && ... args ) ;
(4) (seit C++23)
Hilfsvorlagen
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) ( Nur zur Darstellung* )
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) ( nur zur Darstellung* )
template < class Reference, class C >
constexpr auto /*container-appender*/ ( C & c ) ;
(7) ( exposition only* )
template < class R, class T >

Konzept /*container-compatible-range*/ =
ranges:: input_range < R > &&

std:: convertible_to < ranges:: range_reference_t < R > , T > ;
(8) ( Nur zur Darstellung* )

Die Überladungen der Bereichskonvertierungsfunktion konstruieren ein neues Nicht-View-Objekt aus einem Quellbereich als erstes Argument durch Aufruf eines Konstruktors, der einen Bereich akzeptiert, eines std::from_range_t markierten Bereichskonstruktors, eines Konstruktors, der ein Iterator-Sentinel-Paar akzeptiert, oder durch Rückwärtseinfügen jedes Elements des Quellbereichs in das argumentkonstruierte Objekt.

1) Konstruiert ein Objekt vom Typ C aus den Elementen von r wie folgt:
1) Konstruieren eines Nicht-View-Objekts als ob Direct-Initialisierung (aber nicht Direct-List-Initialisierung) eines Objekts vom Typ C aus dem Quellbereich std:: forward < R > ( r ) und den restlichen Funktionsargumenten std:: forward < Args > ( args ) ... falls std:: constructible_from < C, R, Args... > true ist.
2) Andernfalls wird ein Nicht-View-Objekt so konstruiert, als ob Direct-Initialisierung (aber keine Direct-List-Initialisierung) eines Objekts vom Typ C mit zusätzlichem Disambiguierungs-Tag std:: from_range , dem Quell-Bereich std:: forward < R > ( r ) und den restlichen Funktionsargumenten std:: forward < Args > ( args ) ... durchgeführt wird, falls std:: constructible_from < C, std:: from_range_t , R, Args... > true ist.
3) Andernfalls wird ein Nicht-View-Objekt so konstruiert, als ob Direct-Initialisierung (aber keine Direct-List-Initialisierung) eines Objekts vom Typ C aus dem Iterator-Sentinel-Paar ( ranges:: begin ( r ) als Iterator und ranges:: end ( r ) als Sentinel, wobei Iterator und Sentinel denselben Typ haben müssen (mit anderen Worten: der Quellbereich muss ein Common Range sein), und die restlichen Funktionsargumente std:: forward < Args > ( args ) ... , wenn alle der folgenden Bedingungen true sind:
4) Andernfalls wird ein Nicht-View-Range-Objekt so konstruiert, als würde Direct-Initialisierung (aber keine Direct-List-Initialisierung) eines Objekts vom Typ C aus den restlichen Funktionsargumenten std:: forward < Args > ( args ) ... durchgeführt, mit dem folgenden äquivalenten Aufruf nach der Konstruktion:

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

(bis 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 ) ) ;

(seit C++26)

Wenn R die Bedingung sized_range (bis C++26) approximately_sized_range (seit C++26) erfüllt und C die Bedingung reservable-container erfüllt, kann das konstruierte Objekt c vom Typ C Speicher mit der anfänglichen Speichergröße ranges:: size ( r ) (bis C++26) ranges :: reserve_hint ( r ) (seit C++26) reservieren, um zusätzliche Allokationen während des Einfügens neuer Elemente zu vermeiden. Jedes Element von r wird an c angehängt.

Die obigen Operationen sind gültig, wenn beide der folgenden Bedingungen true sind:

b) Andernfalls ist der Rückgabeausdruck äquivalent zu:

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 ) ... )

Was verschachtelte Bereichskonstruktionen innerhalb des Bereichs ermöglicht, falls ranges:: input_range < ranges:: range_reference_t < C >> true ist.

Andernfalls ist das Programm fehlerhaft.
2) Constructs an object of deduced type from the elements of r .

Sei /*input-iterator*/ ein nur zur Darstellung dienender Typ, der LegacyInputIterator erfüllt:

struct /*Eingabe-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 ; // nicht definiert
pointer operator - > ( ) const ; // nicht definiert
/*Eingabe-Iterator*/ & operator ++ ( ) ; // nicht definiert
/*Eingabe-Iterator*/ operator ++ ( int ) ; // nicht definiert
bool operator == ( const /*Eingabe-Iterator*/ & ) const ; // nicht definiert

} ;
( nur zur Darstellung* )

Sei /*DEDUCE-EXPR*/ wie folgt definiert:

The call is equivalent to zu < decltype ( /*DEDUCE-EXPR*/ ) >
( std:: forward < R > ( r ) , std:: forward < Args > ( args ) ... )
.
3,4) Gibt einen perfekten Weiterleitungsaufruf-Wrapper zurück, der ebenfalls ein RangeAdaptorClosureObject ist.
5) Ist true wenn es ranges:: sized_range erfüllt und für Reservierung geeignet ist.
6) Ist true wenn ein Element vom Typ Reference durch einen Memberfunktionsaufruf von emplace_back , push_back , emplace oder insert an Container angehängt werden kann.
7) Gibt ein Funktionsobjekt zurück, bei dem ein Aufruf des zurückgegebenen Funktionsobjekts ausdrucksäquivalent zum Anhängen eines Elements an einen Container ist. Der Rückgabeausdruck ist äquivalent zu:

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) Wird bei der Definition von Containern verwendet, um einen Eingabebereich R zu konstruieren, dessen Bereichsreferenztyp in T konvertierbar sein muss.

Inhaltsverzeichnis

Parameter

r - ein Quellbereichsobjekt
args - Liste der Argumente zum ( 1,2 ) Konstruieren eines Bereichs oder ( 3,4 ) Binden an die letzten Parameter eines Range-Adapter-Closure-Objekts
Typanforderungen
-
C muss ein cv-unqualifizierter Klassentyp sein ( 1,3 )

Rückgabewert

1,2) Ein konstruiertes Nicht-Ansichtsobjekt.
3,4) Ein Range-Adaptor-Closure-Objekt nicht spezifizierten Typs mit folgenden Eigenschaften:

ranges::to Rückgabetyp

Member-Objekte

Das zurückgegebene Objekt verhält sich, als hätte es kein Zielobjekt, und ein std::tuple Objekt tup konstruiert mit std:: tuple < std:: decay_t < Args > ... > ( std:: forward < Args > ( args ) ... ) , außer dass das Zuweisungsverhalten des zurückgegebenen Objekts nicht spezifiziert ist und die Namen nur zur Darstellung dienen.

Konstruktoren

Der Rückgabetyp von ranges::to ( 3,4 ) verhält sich, als ob seine Kopier-/Verschiebekonstruktoren eine elementweise Kopie/Verschiebung durchführen. Er ist CopyConstructible , wenn alle seine Member-Objekte (oben spezifiziert) CopyConstructible sind, andernfalls ist er MoveConstructible .

Member-Funktion operator()

Gegeben ein Objekt G , erhalten von einem früheren Aufruf von range :: to < /* see below */ > ( args... ) , wenn ein Glvalue g , das G bezeichnet, in einem Funktionsaufrufausdruck g ( r ) aufgerufen wird, findet ein Aufruf des gespeicherten Objekts statt, als ob durch

  • ranges :: to < /* see below */ > ( r, std :: get < Ns > ( g. tup ) ... ) , wobei
  • r ist ein Quell-Range-Objekt, das input_range erfüllen muss.
  • Ns ist ein Integer-Pack 0 , 1 , ..., ( sizeof... ( Args ) - 1 ) .
  • g ist ein Lvalue im Aufrufausdruck, wenn es ein Lvalue im Aufrufausdruck ist, andernfalls ist es ein Rvalue. Daher kann std :: move ( g ) ( r ) die gebundenen Argumente in den Aufruf verschieben, während g ( r ) kopieren würde.
  • Das spezifizierte Template-Argument ist ( 3 ) C oder ( 4 ) der abgeleitete Typ von einem Klassentemplate C , das nicht view erfüllen darf.

Das Programm ist fehlerhaft, wenn g einen volatile-qualifizierten Typ hat.

Ausnahmen

Wirft nur, wenn die Konstruktion eines Non-View-Objekts eine Ausnahme wirft.

Hinweise

Das Einfügen von Elementen in den Container kann Kopiervorgänge beinhalten, die weniger effizient sein können als Verschiebeoperationen, da bei dem Indirektionsaufruf Lvalue-Referenzen erzeugt werden. Benutzer können optional views:: as_rvalue verwenden, um den Bereich so anzupassen, dass dessen Elemente bei dem Indirektionsaufruf stets eine Rvalue-Referenz erzeugen, was eine Verschiebeoperation impliziert.

Die Klammern sind obligatorisch bei Verwendung der Pipe-Syntax.

auto vec = r | std::ranges::to<std::vector>;   // Fehler
auto vec = r | std::ranges::to<std::vector>(); // OK
Feature-Test Makro Wert Std Feature
__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 , und Änderungen an std::ranges::to

Beispiel

Ein Vorschau-Link: 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::zu<std::vector>();
    static_assert(std::same_as<decltype(vec), std::vector<int>>);
    std::println("{}", vec);
    auto list = vec | std::views::take(3) | std::ranges::zu<std::list<double>>();
    std::println("{}", list);
}
void ctor_demos()
{
    // 1.a.1) Direkte Initialisierung
    {
        char array[]{'a', 'b', '\0', 'c'};
        // Argumententyp ist in den Ergebnistyp konvertierbar:
        auto str_to = std::ranges::zu<std::string>(array);
        // Entspricht
        std::string str(array);
        // Der Ergebnistyp ist kein Eingabebereich:
        auto re_to = std::ranges::zu<std::regex>(array);
        // Entspricht
        std::regex re(array);
    }
    // 1.a.2) from_range Konstruktor
    {
        auto list = {'a', 'b', '\0', 'c'};
        // Argumententyp ist in den Ergebnistyp konvertierbar:
        auto str_to = std::ranges::zu<std::string>(list);
        // Entspricht
        // std::string str(std::from_range, list);
        // Der Ergebnistyp ist kein Eingabebereich:
        [[maybe_unused]]
        auto pair_to = std::ranges::zu<std::pair<std::from_range_t, bool>>(true);
        // Entspricht
        std::pair<std::from_range_t, bool> pair(std::from_range, true);
    }
    // 1.a.3) Iterator-Paar-Konstruktor
    {
        auto list = {'a', 'b', '\0', 'c'};
        // Argumententyp ist in den Ergebnistyp konvertierbar:
        auto devector_to = std::ranges::zu<boost::Container::devector<char>>(list);
        // Entspricht
        boost::Container::devector<char> devector(std::ranges::begin(list),
                                                  std::ranges::end(list));
        // Der Ergebnistyp ist kein Eingabebereich:
        std::regex re;
        auto it_to = std::ranges::zu<std::cregex_iterator>(list, re);
        // Entspricht
        std::cregex_iterator it(std::ranges::begin(list), std::ranges::end(list), re);
    }
}

Ausgabe:

[2, 4, 6, 8]
[2, 4, 6]

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
LWG 3984 C++23 der verschachtelte Konstruktionszweig von ranges::to führte zu
Programm ill-formed wenn R& kein viewable_range modelliert
als well-formed festgelegt
LWG 4016 C++23 der Container-Einfügezweig von
ranges::to beinhaltete Verwendung von Insert-Iteratoren
ersetzt durch direktes Anhängen
von Elementen an Container

Referenzen

  • C++23-Standard (ISO/IEC 14882:2024):
  • 26.5.7 Bereichskonvertierungen [range.utility.conv]