std::ranges::to
| Definiert in Header <ranges>
|
||
template< class C, ranges::input_range R, class... Args >
requires (!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 adaptor 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) | (nur zur Darstellung*) |
template< class R, class T >
concept /*container-compatible-range*/ =
ranges::input_range<R> &&
std::convertible_to<ranges::range_reference_t<R>, T>;
|
(8) | (nur zur Darstellung*) |
Die Überladungen der Range-Konvertierungsfunktion konstruieren ein neues Nicht-View-Objekt aus einem Quell-Range als erstes Argument, indem sie einen Konstruktor aufrufen, der einen Range, einen mit std::from_range_t getaggten Range-Konstruktor, einen Konstruktor, der ein Iterator-Sentinel-Paar akzeptiert, oder indem sie jedes Element des Quell-Ranges per Back-Insertion in das aus den Argumenten konstruierte Objekt einfügt.
C aus den Elementen von r wie folgt:C nicht input_range erfüllt oder std::convertible_to<ranges::range_reference_t<R>, ranges::range_value_t<C>> ist true:C aus dem Quell-Range std::forward<R>(r) und den restlichen Funktionsargumenten std::forward<Args>(args)..., falls std::constructible_from<C, R, Args...> ist true.C aus dem zusätzlichen Disambiguierungs-Tag std::from_range, dem Quell-Range std::forward<R>(r) und den restlichen Funktionsargumenten std::forward<Args>(args)..., falls std::constructible_from<C, std::from_range_t, R, Args...> ist true.C aus dem Iterator-Sentinel-Paar (ranges::begin(r) als Iterator und ranges::end(r) als Sentinel, wobei Iterator und Sentinel denselben Typ haben. Mit anderen Worten, der Quell-Range muss ein common_range sein), und den restlichen Funktionsargumenten std::forward<Args>(args)..., falls alle der folgenden Bedingungen true sind:
ranges::common_range<R>- Falls
std::iterator_traits<ranges::iterator_t<R>>::iterator_categorygültig ist und einen Typ bezeichnet, derstd::derived_from<std::input_iterator_tag> std::constructible_from<C, ranges::iterator_t<R>, ranges::sentinel_t<R>, Args...>
C aus den restlichen Funktionsargumenten std::forward<Args>(args)... mit dem folgenden äquivalenten Aufruf unten nach der Konstruktion:
|
|
(bis C++26) |
|
|
(seit C++26) |
Falls das
R sized_range(bis C++26)approximately_sized_range(seit C++26) und C 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, falls 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 Range-Konstruktionen innerhalb des Ranges erlaubt, falls ranges::input_range<ranges::range_reference_t<C>> ist true.
r.
Sei /*input-iterator*/ ein Nur-zur-Darstellung-Typ, der LegacyInputIterator erfüllt:
struct /*input-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; // not defined
pointer operator->() const; // not defined
/*input-iterator*/& operator++(); // not defined
/*input-iterator*/ operator++(int); // not defined
bool operator==(const /*input-iterator*/&) const; // not defined
};
|
(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.
Der Aufruf ist äquivalent zu
to<decltype(/*DEDUCE-EXPR*/)> (std::forward<R>(r), std::forward<Args>(args)...).true, falls es ranges::sized_range erfüllt und berechtigt ist, reservierbar zu sein.true, falls ein Element vom Typ Reference an Container durch einen Memberfunktionsaufruf emplace_back, push_back, emplace oder insert 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 verwendet, dessen Range-Referenztyp in T konvertierbar sein muss.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 Vorschaulink: Compiler Explorer
#include <boost/container/devector.hpp>
#include <concepts>
#include <initializer_list>
#include <list>
#include <print>
#include <ranges>
#include <regex>
#include <string>
#include <vector>
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("1) {}", vec);
auto list = vec | std::views::take(3) | std::ranges::to<std::list<double>>();
std::println("2) {}", 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);
}
}
Ausgabe:
1) [2, 4, 6, 8]
2) [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]