Namespaces
Variants

std::ranges:: to

From cppreference.net
Ranges library
Range adaptors
Défini dans l'en-tête <ranges>
template < class C, ranges:: input_range R, class ... Args >

requires ( ! ranges:: view < C > )

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

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

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

requires ( ! ranges:: view < C > )

constexpr /*adaptateur de fermeture de plage*/ to ( Args && ... args ) ;
(3) (depuis C++23)
template < template < class ... > class C, class ... Args >
constexpr /*adaptateur de plage de fermeture*/ to ( Args && ... args ) ;
(4) (depuis C++23)
Modèles d'assistance
template < class Container >

constexpr bool /*conteneur-réservable*/ =
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) ( exposition uniquement* )
template < class Container, class Reference >

constexpr bool /*ajoutable-au-conteneur*/ =
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) ( exposition uniquement* )
template < class Reference, class C >
constexpr auto /*container-appender*/ ( C & c ) ;
(7) ( exposition uniquement* )
template < class R, class T >

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

std:: convertible_to < ranges:: range_reference_t < R > , T > ;
(8) ( exposition uniquement* )

Les surcharges de la fonction de conversion de plage construisent un nouvel objet non-vue à partir d'une plage source comme premier argument en appelant un constructeur prenant une plage, un std::from_range_t constructeur de plage étiqueté, un constructeur prenant une paire itérateur-sentinelle, ou en insérant en arrière chaque élément de la plage source dans l'objet construit par les arguments.

1) Construit un objet de type C à partir des éléments de r de la manière suivante :
1) Construire un objet non-vue comme si on initialisait directement (mais pas par initialisation de liste directe) un objet de type C à partir de la plage source std:: forward < R > ( r ) et des autres arguments fonctionnels std:: forward < Args > ( args ) ... si std:: constructible_from < C, R, Args... > est true .
2) Sinon, construction d'un objet non-vue comme si on initialisait directement (mais pas par initialisation de liste directe) un objet de type C à partir du tag de désambiguïsation supplémentaire std:: from_range , la plage source std:: forward < R > ( r ) et les autres arguments fonctionnels std:: forward < Args > ( args ) ... si std:: constructible_from < C, std:: from_range_t , R, Args... > est true .
3) Sinon, construction d'un objet non-vue comme si on initialisait directement (mais pas par initialisation de liste directe) un objet de type C à partir de la paire itérateur-sentinelle ( ranges:: begin ( r ) comme itérateur et ranges:: end ( r ) comme sentinelle, où l'itérateur et la sentinelle ont le même type. En d'autres termes, la plage source doit être une plage commune), et les autres arguments de fonction std:: forward < Args > ( args ) ... si toutes les conditions suivantes sont true :
4) Sinon, construction d'un objet de plage non-vue comme si on initialisait directement (mais pas par initialisation de liste directe) un objet de type C à partir des autres arguments de la fonction std:: forward < Args > ( args ) ... avec l'appel équivalent suivant après la construction :

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

(jusqu'en 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 ) ) ;

(depuis C++26)

Si R satisfait sized_range (jusqu'en C++26) approximately_sized_range (depuis C++26) et C satisfait reservable-container , l'objet construit c de type C peut réserver du stockage avec la taille de stockage initiale ranges:: size ( r ) (jusqu'en C++26) ranges :: reserve_hint ( r ) (depuis C++26) pour éviter des allocations supplémentaires lors de l'insertion de nouveaux éléments. Chaque élément de r est ajouté à c .

Les opérations ci-dessus sont valides si les deux conditions suivantes sont true :

b) Sinon, l'expression de retour est équivalente à :

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

Ce qui permet les constructions de plages imbriquées à l'intérieur de la plage si ranges:: input_range < ranges:: range_reference_t < C >> est true .

Sinon, le programme est mal formé.
2) Constructs an object of deduced type from the elements of r .

Soit /*input-iterator*/ un type d'exposition uniquement qui satisfait LegacyInputIterator :

struct /*itérateur-entrée*/

{
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 ; // non défini
pointer operator - > ( ) const ; // non défini
/*itérateur-entrée*/ & operator ++ ( ) ; // non défini
/*itérateur-entrée*/ operator ++ ( int ) ; // non défini
bool operator == ( const /*itérateur-entrée*/ & ) const ; // non défini

} ;
( exposition uniquement* )

Soit /*DEDUCE-EXPR*/ défini comme suit :

The call is equivalent to vers < decltype ( /*DEDUCE-EXPR*/ ) >
( std:: forward < R > ( r ) , std:: forward < Args > ( args ) ... )
.
3,4) Renvoie un wrapper d'appel à transfert parfait qui est également un RangeAdaptorClosureObject .
5) Est true s'il satisfait ranges:: sized_range et est éligible à être réservable.
6) Est true si un élément de type Reference peut être ajouté à Container via un appel de fonction membre emplace_back , push_back , emplace ou insert .
7) Retourne un objet fonction où un appel à l'objet fonction retourné est expression-équivalent à l'ajout d'un élément à un conteneur. L'expression de retour est équivalente à :

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) Est utilisé dans la définition des conteneurs pour construire une plage d'entrée R dont le type de référence de plage doit être convertible en T .

Table des matières

Paramètres

r - un objet de plage source
args - liste des arguments pour ( 1,2 ) construire une plage ou ( 3,4 ) lier aux derniers paramètres de l'objet de fermeture d'adaptateur de plage
Exigences de type
-
C doit être un type de classe non qualifié cv ( 1,3 )

Valeur de retour

1,2) Un objet non-vue construit.
3,4) Un objet de fermeture d'adaptateur de plage de type non spécifié, avec les propriétés suivantes :

ranges::to type de retour

Objets membres

L'objet retourné se comporte comme s'il n'avait pas d'objet cible, et un objet std::tuple tup construit avec std:: tuple < std:: decay_t < Args > ... > ( std:: forward < Args > ( args ) ... ) , sauf que le comportement d'affectation de l'objet retourné n'est pas spécifié et les noms sont uniquement à titre d'exposition.

Constructeurs

Le type de retour de ranges::to ( 3,4 ) se comporte comme si ses constructeurs de copie/déplacement effectuaient une copie/déplacement membre par membre. Il est CopyConstructible si tous ses objets membres (spécifiés ci-dessus) sont CopyConstructible , et est MoveConstructible sinon.

Fonction membre operator()

Étant donné un objet G obtenu d'un appel antérieur à range :: to < /* see below */ > ( args... ) , lorsqu'une glvalue g désignant G est invoquée dans une expression d'appel de fonction g ( r ) , un appel de l'objet stocké a lieu, comme par

  • ranges :: to < /* see below */ > ( r, std :: get < Ns > ( g. tup ) ... ) , où
  • r est un objet plage source qui doit satisfaire input_range .
  • Ns est un pack d'entiers 0 , 1 , ..., ( sizeof... ( Args ) - 1 ) .
  • g est une lvalue dans l'expression d'appel si c'est une lvalue dans l'expression d'appel, et est une rvalue sinon. Ainsi std :: move ( g ) ( r ) peut déplacer les arguments liés dans l'appel, où g ( r ) copierait.
  • L'argument template spécifié est ( 3 ) C ou ( 4 ) le type déduit d'un template de classe C qui ne doit pas satisfaire view .

Le programme est mal formé si g a un type qualifié volatile.

Exceptions

Ne lance que si la construction d'un objet non-vue lève une exception.

Notes

L'insertion d'éléments dans le conteneur peut impliquer une copie qui peut être moins efficace que le déplacement car des références lvalue sont produites lors de l'appel d'indirection. Les utilisateurs peuvent opter pour utiliser views:: as_rvalue pour adapter la plage afin que leurs éléments produisent toujours une référence rvalue lors de l'appel d'indirection, ce qui implique un déplacement.

Les parenthèses sont obligatoires lors de l'utilisation de la syntaxe de pipe.

auto vec = r | std::ranges::to<std::vector>;   // Erreur
auto vec = r | std::ranges::to<std::vector>(); // Correct
Macro de test de fonctionnalité Valeur Std Fonctionnalité
__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 , et modifications de std::ranges::to

Exemple

Un lien de prévisualisation : 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::à<std::vector>();
    static_assert(std::same_as<decltype(vec), std::vector<int>>);
    std::println("{}", vec);
    auto list = vec | std::views::take(3) | std::ranges::à<std::list<double>>();
    std::println("{}", list);
}
void ctor_demos()
{
    // 1.a.1) Initialisation directe
    {
        char array[]{'a', 'b', '\0', 'c'};
        // Le type d'argument est convertible en type de valeur de résultat :
        auto str_to = std::ranges::à<std::string>(array);
        // Équivalent à
        std::string str(array);
        // Le type de résultat n'est pas une plage d'entrée :
        auto re_to = std::ranges::à<std::regex>(array);
        // Équivalent à
        std::regex re(array);
    }
    // 1.a.2) constructeur from_range
    {
        auto list = {'a', 'b', '\0', 'c'};
        // Le type d'argument est convertible en type de valeur de résultat :
        auto str_to = std::ranges::à<std::string>(list);
        // Équivalent à
        // std::string str(std::from_range, list);
        // Le type de résultat n'est pas une plage d'entrée :
        [[maybe_unused]]
        auto pair_to = std::ranges::à<std::pair<std::from_range_t, bool>>(true);
        // Équivalent à
        std::pair<std::from_range_t, bool> pair(std::from_range, true);
    }
    // 1.a.3) constructeur avec paire d'itérateurs
    {
        auto list = {'a', 'b', '\0', 'c'};
        // Le type d'argument est convertible en type de valeur de résultat :
        auto devector_to = std::ranges::à<boost::container::devector<char>>(list);
        // Équivalent à
        boost::container::devector<char> devector(std::ranges::begin(list),
                                                  std::ranges::end(list));
        // Le type de résultat n'est pas une plage d'entrée :
        std::regex re;
        auto it_to = std::ranges::à<std::cregex_iterator>(list, re);
        // Équivalent à
        std::cregex_iterator it(std::ranges::begin(list), std::ranges::end(list), re);
    }
}

Sortie :

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

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Applicable à Comportement publié Comportement corrigé
LWG 3984 C++23 la branche de construction imbriquée de ranges::to rendait le programme
mal formé si R& ne modélise pas viewable_range
rendu bien formé
LWG 4016 C++23 la branche d'insertion de conteneur de
ranges::to impliquait l'utilisation d'itérateurs d'insertion
remplacée par l'ajout direct
d'éléments au conteneur

Références

  • Norme C++23 (ISO/CEI 14882:2024) :
  • 26.5.7 Conversions de plages [range.utility.conv]