Namespaces
Variants

std::tuple<Types...>::tuple

Depuis fr.cppreference.net
 
 
Bibliothèque d'utilitaires
Support linguistique
Support des types (types de base, RTTI)
Macros de test de fonctionnalités de la bibliothèque (C++20)
Utilitaires de programme
Fonctions variadiques
Support des coroutines (C++20)
Support des contrats (C++26)
Comparaison à trois voies
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Utilitaires généraux
Opérateurs relationnels (obsolète en C++20)
 
 
Défini dans l'en-tête <tuple>
constexpr tuple();
(1) (depuis C++11)
(explicite conditionnellement)
tuple( const Types&... args );
(2) (depuis C++11)
(constexpr depuis C++14)
(explicite conditionnellement)
template< class... UTypes >
tuple( UTypes&&... args );
(3) (depuis C++11)
(constexpr depuis C++14)
(explicite conditionnellement)
template< class... UTypes >
constexpr tuple( tuple<UTypes...>& other );
(4) (depuis C++23)
(explicite conditionnellement)
template< class... UTypes >
tuple( const tuple<UTypes...>& other );
(5) (depuis C++11)
(constexpr depuis C++14)
(explicite conditionnellement)
template< class... UTypes >
tuple( tuple<UTypes...>&& other );
(6) (depuis C++11)
(constexpr depuis C++14)
(explicite conditionnellement)
template< class... UTypes >
constexpr tuple( const tuple<UTypes...>&& other );
(7) (depuis C++23)
(explicite conditionnellement)
template< class U1, class U2 >
constexpr tuple( std::pair<U1, U2>& p );
(8) (depuis C++23)
(explicite conditionnellement)
template< class U1, class U2 >
tuple( const std::pair<U1, U2>& p );
(9) (depuis C++11)
(constexpr depuis C++14)
(explicite conditionnellement)
template< class U1, class U2 >
tuple( std::pair<U1, U2>&& p );
(10) (depuis C++11)
(constexpr depuis C++14)
(explicite conditionnellement)
template< class U1, class U2 >
constexpr tuple( const std::pair<U1, U2>&& p );
(11) (depuis C++23)
(explicite conditionnellement)
template< tuple-like UTuple >
constexpr tuple( UTuple&& u );
(12) (depuis C++23)
(explicite conditionnellement)
tuple( const tuple& other ) = default;
(13) (depuis C++11)
tuple( tuple&& other ) = default;
(14) (depuis C++11)
Constructeurs étendus avec allocateur
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a );
(15) (depuis C++11)
(constexpr depuis C++20)
(explicite conditionnellement)
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a,
       const Types&... args );
(16) (depuis C++11)
(constexpr depuis C++20)
(explicite conditionnellement)
template< class Alloc, class... UTypes >
tuple( std::allocator_arg_t, const Alloc& a,
       UTypes&&... args );
(17) (depuis C++11)
(constexpr depuis C++20)
(explicite conditionnellement)
template< class Alloc, class... UTypes >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 tuple<UTypes...>& other );
(18) (depuis C++23)
(explicite conditionnellement)
template< class Alloc, class... UTypes >
tuple( std::allocator_arg_t, const Alloc& a,
       const tuple<UTypes...>& other );
(19) (depuis C++11)
(constexpr depuis C++20)
(explicite conditionnellement)
template< class Alloc, class... UTypes >
tuple( std::allocator_arg_t, const Alloc& a,
       tuple<UTypes...>&& other );
(20) (depuis C++11)
(constexpr depuis C++20)
(explicite conditionnellement)
template< class Alloc, class... UTypes >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 const tuple<UTypes...>&& other );
(21) (depuis C++23)
(explicite conditionnellement)
template< class Alloc, class U1, class U2 >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 std::pair<U1, U2>& p );
(22) (depuis C++23)
(explicite conditionnellement)
template< class Alloc, class U1, class U2 >
tuple( std::allocator_arg_t, const Alloc& a,
       const std::pair<U1, U2>& p );
(23) (depuis C++11)
(constexpr depuis C++20)
(explicite conditionnellement)
template< class Alloc, class U1, class U2 >
tuple( std::allocator_arg_t, const Alloc& a,
       std::pair<U1, U2>&& p );
(24) (depuis C++11)
(constexpr depuis C++20)
(explicite conditionnellement)
template< class Alloc, class U1, class U2 >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 const std::pair<U1, U2>&& p );
(25) (depuis C++23)
(explicite conditionnellement)
template< class Alloc, tuple-like UTuple >
constexpr tuple( std::allocator_arg_t, const Alloc& a, UTuple&& u );
(26) (depuis C++23)
(explicite conditionnellement)
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a,
       const tuple& other );
(27) (depuis C++11)
(constexpr depuis C++20)
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a,
       tuple&& other );
(28) (depuis C++11)
(constexpr depuis C++20)

Construit un nouveau tuple.

Dans les descriptions qui suivent, soit

  • i dans l'intervalle [0sizeof...(Types)) dans l'ordre,
  • Ti le ième type dans Types, et
  • Ui le ième type dans un pack de paramètres de modèle nommé UTypes,

où l'indexation est basée sur zéro.

1) Constructeur par défaut. Initialise par valeur tous les éléments, s'il y en a. Le constructeur par défaut est trivial si sizeof...(Types) == 0.
  • Cette surcharge participe à la résolution de surcharge uniquement si std::is_default_constructible<Ti>::value est true pour tous les i.
  • Le constructeur est explicit si et seulement si Ti n'est pas initialisable par liste de copie à partir de {} pour au moins un i.
2) Constructeur direct. Initialise chaque élément du tuple avec le paramètre correspondant.
  • Cette surcharge participe à la résolution de surcharge uniquement si sizeof...(Types) >= 1 et std::is_copy_constructible<Ti>::value est true pour tous les i.
  • Ce constructeur est explicit si et seulement si std::is_convertible<const Ti&, Ti>::value est false pour au moins un i.
3) Constructeur de conversion. Initialise chaque élément du tuple avec la valeur correspondante dans std::forward<UTypes>(args).
  • Cette surcharge participe à la résolution de surcharge uniquement si
    • sizeof...(Types) == sizeof...(UTypes),
    • sizeof...(Types) >= 1,
    • std::is_constructible<Ti, Ui>::value est true pour tous les i, et
    • soit D soit std::decay<U0>::type(jusqu'à C++20)std::remove_cvref_t<U0>(depuis C++20),
      • si sizeof...(Types) == 1, alors D n'est pas std::tuple, sinon,
      • si sizeof...(Types) == 2 ou sizeof...(Types) == 3, alors soit D n'est pas std::allocator_arg_t, ou T0 est std::allocator_arg_t.
  • Le constructeur est explicit si et seulement si std::is_convertible<Ui, Ti>::value est false pour au moins un i.
(depuis C++23)
4-7) Constructeur de conversion. Initialise chaque élément du tuple avec l'élément correspondant de other.

Formellement, soit FWD(other) soit std::forward<decltype(other)>(other), pour tous les i, initialise le ième élément du tuple avec std::get<i>(FWD(other)).

  • Cette surcharge participe à la résolution de surcharge uniquement si
    • sizeof...(Types) == sizeof...(UTypes),
    • std::is_constructible_v<Ti, decltype(std::get<i>(FWD(other)))> est true pour tous les i, et
    • soit
      • sizeof...(Types) n'est pas 1, ou
      • (lorsque Types... se développe en T et UTypes... se développe en U) std::is_convertible_v<decltype(other), T>, std::is_constructible_v<T, decltype(other)>, et std::is_same_v<T, U> sont tous false.
  • Ces constructeurs sont explicit si et seulement si std::is_convertible_v<decltype(std::get<i>(FWD(other))), Ti> est false pour au moins un i.
  • Ces constructeurs sont définis comme supprimés si l'initialisation d'un élément qui est une référence le lie à un objet temporaire.
(depuis C++23)
8-11) Constructeur de paire. Construit un tuple de 2 éléments dont chaque élément est construit à partir de l'élément correspondant de p.

Formellement, soit FWD(p) soit std::forward<decltype(p)>(p), initialise le premier élément avec std::get<0>(FWD(p)) et le second élément avec std::get<1>(FWD(p)).

  • Cette surcharge participe à la résolution de surcharge uniquement si
    • sizeof...(Types) == 2,
    • std::is_constructible_v<T0, decltype(std::get<0>(FWD(p)))> est true, et
    • std::is_constructible_v<T1, decltype(std::get<1>(FWD(p)))> est true.
  • Le constructeur est explicit si et seulement si std::is_convertible_v<decltype(std::get<0>(FWD(p))), T0> ou std::is_convertible_v<decltype(std::get<1>(FWD(p))), T1> est false.
  • Ces constructeurs sont définis comme supprimés si l'initialisation d'un élément qui est une référence le lie à un objet temporaire.
(depuis C++23)
12) tuple-like constructeur. Construit un tuple dont chaque élément est construit à partir de l'élément correspondant de u.

Formellement, pour tous les i, initialise le ième élément du tuple avec std::get<i>(std::forward<UTuple>(u)).

  • Cette surcharge participe à la résolution de surcharge uniquement si
    • std::same_as<std::remove_cvref_t<UTuple>, std::tuple> est false,
    • std::remove_cvref_t<UTuple> n'est pas une spécialisation de std::ranges::subrange,
    • sizeof...(Types) est égal à std::tuple_size_v<std::remove_cvref_t<UTuple>>,
    • std::is_constructible_v<Ti, decltype(std::get<i>(std::forward<UTuple>(u)))> est true pour tous les i, et
    • soit
      • sizeof...(Types) n'est pas 1, ou
      • (lorsque Types... se développe en T) std::is_convertible_v<UTuple, T> et std::is_constructible_v<T, UTuple> sont tous deux false.
  • Ce constructeur est défini comme supprimé si l'initialisation d'un élément qui est une référence le lie à un objet temporaire.
13) Constructeur de copie implicitement défini. Initialise chaque élément du tuple avec l'élément correspondant de other.
  • Ce constructeur est constexpr si chaque opération qu'il effectue est constexpr. Pour le tuple vide std::tuple<>, il est constexpr.
  • std::is_copy_constructible<Ti>::value doit être true pour tous les i, sinon le comportement est indéfini(jusqu'à C++20)le programme est mal formé(depuis C++20).
14) Constructeur de déplacement implicitement défini. Pour tous les i, initialise le ième élément du tuple avec std::forward<Ui>(std::get<i>(other)).
  • Ce constructeur est constexpr si chaque opération qu'il effectue est constexpr. Pour le tuple vide std::tuple<>, il est constexpr.
  • std::is_move_constructible<Ti>::value doit être true pour tous les i, sinon le comportement est indéfini(jusqu'à C++20)cette surcharge ne participe pas à la résolution de surcharge(depuis C++20).
15-28) Identique à (1-14) sauf que chaque élément est créé par construction avec allocateur, c'est-à-dire que l'objet Allocateur a est passé comme argument supplémentaire au constructeur de chaque élément pour lequel std::uses_allocator<Ui, Alloc>::value est true.

Paramètres

args - valeurs utilisées pour initialiser chaque élément du tuple
other - le tuple de valeurs utilisées pour initialiser chaque élément du tuple
p - la paire de valeurs utilisée pour initialiser les deux éléments du 2-tuple
u - l'objet tuple-like de valeurs utilisées pour initialiser chaque élément du tuple
a - l'allocateur à utiliser dans la construction avec allocateur

Notes

Les constructeurs conditionnellement explicites permettent de construire un tuple dans un contexte d'initialisation par copie en utilisant la syntaxe d'initialisation par liste :

std::tuple<int, int> foo_tuple() 
{
    // return {1, -1};             // Erreur avant N4387
    return std::make_tuple(1, -1); // Fonctionne toujours
}

Notez que si un élément de la liste n'est pas implicitement convertible vers l'élément correspondant du tuple cible, les constructeurs deviennent explicites :

using namespace std::chrono;
void launch_rocket_at(std::tuple<hours, minutes, seconds>);
launch_rocket_at({hours(1), minutes(2), seconds(3)}); // OK
launch_rocket_at({1, 2, 3}); // Erreur : int n'est pas implicitement convertible en duration
launch_rocket_at(std::tuple<hours, minutes, seconds>{1, 2, 3}); // OK

Exemple

#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <vector>
// fonction auxiliaire pour afficher un vecteur vers un flux
template<class Os, class T>
Os& operator<<(Os& os, std::vector<T> const& v)
{
    os << '{';
    for (auto i{v.size()}; const T& e : v)
        os << e << (--i ? "," : "");
    return os << '}';
}
template<class T>
void print_single(T const& v)
{
    if constexpr (std::is_same_v<T, std::decay_t<std::string>>)
        std::cout << std::quoted(v);
    else if constexpr (std::is_same_v<std::decay_t<T>, char>)
        std::cout << "'" << v << "'";
    else
        std::cout << v;
}
// fonction d'assistance pour afficher un tuple de n'importe quelle taille
template<class Tuple, std::size_t N>
struct TuplePrinter
{
    static void print(const Tuple& t)
    {
        TuplePrinter<Tuple, N - 1>::print(t);
        std::cout << ", ";
        print_single(std::obtenir<N - 1>(t));
    }
};
template<class Tuple>
struct TuplePrinter<Tuple, 1>
{
    static void print(const Tuple& t)
    {
        print_single(std::obtenir<0>(t));
    }
};
template<class... Args>
void print(std::string_view message, const std::tuple<Args...>& t)
{
    std::cout << message << " (";
    TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
    std::cout << ")\n";
}
// fin de la fonction d'assistance
int main()
{
    std::tuple<int, std::string, double> t1;
    print("Initialisé par valeur, t1:", t1);
    std::tuple<int, std::string, double> t2{42, "Test", -3.14};
    print("Initialisé avec des valeurs, t2:", t2);
    std::tuple<char, std::string, int> t3{t2};
    print("Converti implicitement, t3:", t3);
    std::tuple<int, double> t4{std::make_pair(42, 3.14)};
    print("Construit à partir d'une paire, t4:", t4);
    // étant donné Allocator my_alloc avec un constructeur à un seul argument
    // my_alloc(int); utilisez my_alloc(1) pour allouer 5 entiers dans un vecteur
    using my_alloc = std::allocator<int>;
    std::vector<int, my_alloc> v{5, 1, my_alloc{/* 1 */}};
    // utiliser my_alloc(2) pour allouer 5 entiers dans un vecteur dans un tuple
    std::tuple<int, std::vector<int, my_alloc>, double> t5
        {std::allocator_arg, my_alloc{/* 2 */}, 42, v, -3.14};
    print("Construit avec allocateur, t5:", t5);
}

Sortie possible :

Initialisé par valeur, t1: (0, "", 0)
Initialisé avec des valeurs, t2: (42, "Test", -3.14)
Conversion implicite, t3: ('*', "Test", -3)
Construit à partir d'une paire, t4: (42, 3.14)
Construit avec un allocateur, t5: (42, {1,1,1,1,1}, -3.14)

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 Appliqué à Comportement publié Comportement corrigé
LWG 2510 C++11 le constructeur par défaut était implicite rendu conditionnellement explicite
LWG 3121 C++11 le constructeur de tuple à 1 élément pouvait vérifier récursivement les contraintes ;
allocator_arg_t provoquait une ambiguïté
contraintes renforcées
pour le constructeur
LWG 3158 C++11 le constructeur utilisant l'allocateur correspondant
au constructeur par défaut était implicite
rendu conditionnellement explicite
LWG 3211 C++11 le caractère trivial du constructeur par défaut de
tuple<> n'était pas spécifié
requis d'être trivial
LWG 4045 C++23 tuple-like le constructeur pouvait potentiellement créer des références pendantes défini comme supprimé
N4387 C++11 certains constructeurs étaient explicites, empêchant des comportements utiles la plupart des constructeurs rendus
conditionnellement explicites

Voir aussi

assigne le contenu d'un tuple à un autre
(fonction membre publique)
(C++11)
crée un objet tuple du type défini par les types d'arguments
(modèle de fonction)
(C++11)
crée un tuple de références lvalue ou décompose un tuple en objets individuels
(modèle de fonction)
crée un tuple de références de transfert
(modèle de fonction)
construit un nouveau pair
(fonction membre publique de std::pair<T1,T2> )