std::ranges:: to
|
Definiert im Header
<ranges>
|
||
|
template
<
class
C,
ranges::
input_range
R,
class
...
Args
>
erfordert
(
!
ranges::
view
<
C
>
)
|
(1) | (seit C++23) |
|
template
<
template
<
class
...
>
class
C,
ranges::
input_range
R,
class
...
Args
>
|
(2) | (seit C++23) |
|
template
<
class
C,
class
...
Args
>
requires
(
!
ranges::
view
<
C
>
)
|
(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*/
=
|
(5) | ( Nur zur Darstellung* ) |
|
template
<
class
Container,
class
Reference
>
constexpr
bool
/*container-appendable*/
=
|
(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*/
=
|
(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.
C
aus den Elementen von
r
wie folgt:
C
nicht
input_range
oder
std::
convertible_to
<
ranges::
range_reference_t
<
R
>
,
ranges::
range_value_t
<
C
>>
erfüllt:
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.
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.
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:
- ranges:: common_range < R >
- Falls std:: iterator_traits < ranges:: iterator_t < R >> :: iterator_category gültig ist und einen Typ bezeichnet, der std:: derived_from < std:: input_iterator_tag > erfüllt
- std:: constructible_from < C, ranges:: iterator_t < R > , ranges:: sentinel_t < R > , Args... >
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
>
)
|
(bis C++26) |
|
if
constexpr
(
ranges
::
approximately_sized_range
<
R
>
|
(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:
- 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
)
...
)
Was verschachtelte Bereichskonstruktionen innerhalb des Bereichs ermöglicht, falls
ranges::
input_range
<
ranges::
range_reference_t
<
C
>>
true
ist.
Sei /*input-iterator*/ ein nur zur Darstellung dienender Typ, der LegacyInputIterator erfüllt:
|
struct
/*Eingabe-Iterator*/
{
|
( nur zur Darstellung* ) | |
Sei /*DEDUCE-EXPR*/ wie folgt definiert:
- C ( std:: declval < R > ( ) , std:: declval < Args > ( ) ... ) , falls dieser Ausdruck gültig ist.
-
Andernfalls,
C
(
std::
from_range
,
std::
declval
<
R
>
(
)
,
std:: declval < Args > ( ) ... ) , falls dieser Ausdruck gültig ist. -
Andernfalls,
C
(
std::
declval
<
/*input-iterator*/
>
(
)
,
std:: declval < /*input-iterator*/ > ( ) ,
std:: declval < Args > ( ) ... ) , falls dieser Ausdruck gültig ist. - Andernfalls ist das Programm fehlerhaft.
( std:: forward < R > ( r ) , std:: forward < Args > ( args ) ... ) .
Reference
durch einen Memberfunktionsaufruf von
emplace_back
,
push_back
,
emplace
oder
insert
an
Container
angehängt werden kann.
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
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
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_rangeerfü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
)
Coder ( 4 ) der abgeleitete Typ von einem KlassentemplateC, das nichtviewerfüllen darf.
-
r
ist ein Quell-Range-Objekt, das
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]