Namespaces
Variants

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

С ru.cppreference.net
 
 
Библиотека утилит
Поддержка языка
Поддержка типов (базовые типы, RTTI)
Макросы тестирования возможностей библиотеки (C++20)
Утилиты программы
Функции с переменным числом аргументов
Поддержка корутин (C++20)
Поддержка контрактов (C++26)
Трёхстороннее сравнение
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Общие утилиты
Реляционные операторы (устарело в C++20)
 
 
Определено в заголовке <tuple>
constexpr tuple();
(1) (начиная с C++11)
(условно явный)
tuple( const Types&... args );
(2) (начиная с C++11)
(constexpr начиная с C++14)
(условно явный)
template< class... UTypes >
tuple( UTypes&&... args );
(3) (начиная с C++11)
(constexpr начиная с C++14)
(условно явный)
template< class... UTypes >
constexpr tuple( tuple<UTypes...>& other );
(4) (начиная с C++23)
(условно явный)
template< class... UTypes >
tuple( const tuple<UTypes...>& other );
(5) (начиная с C++11)
(constexpr начиная с C++14)
(условно явный)
template< class... UTypes >
tuple( tuple<UTypes...>&& other );
(6) (начиная с C++11)
(constexpr начиная с C++14)
(условно явный)
template< class... UTypes >
constexpr tuple( const tuple<UTypes...>&& other );
(7) (начиная с C++23)
(условно явный)
template< class U1, class U2 >
constexpr tuple( std::pair<U1, U2>& p );
(8) (начиная с C++23)
(условно явный)
template< class U1, class U2 >
tuple( const std::pair<U1, U2>& p );
(9) (начиная с C++11)
(constexpr начиная с C++14)
(условно явный)
template< class U1, class U2 >
tuple( std::pair<U1, U2>&& p );
(10) (начиная с C++11)
(constexpr начиная с C++14)
(условно явный)
template< class U1, class U2 >
constexpr tuple( const std::pair<U1, U2>&& p );
(11) (начиная с C++23)
(условно явный)
template< tuple-like UTuple >
constexpr tuple( UTuple&& u );
(12) (начиная с C++23)
(условно явный)
tuple( const tuple& other ) = default;
(13) (начиная с C++11)
tuple( tuple&& other ) = default;
(14) (начиная с C++11)
Конструкторы с расширением аллокатора
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a );
(15) (начиная с C++11)
(constexpr начиная с C++20)
(условно явный)
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a,
       const Types&... args );
(16) (начиная с C++11)
(constexpr начиная с C++20)
(условно явный)
template< class Alloc, class... UTypes >
tuple( std::allocator_arg_t, const Alloc& a,
       UTypes&&... args );
(17) (начиная с C++11)
(constexpr начиная с C++20)
(условно явный)
template< class Alloc, class... UTypes >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 tuple<UTypes...>& other );
(18) (начиная с C++23)
(условно явный)
template< class Alloc, class... UTypes >
tuple( std::allocator_arg_t, const Alloc& a,
       const tuple<UTypes...>& other );
(19) (начиная с C++11)
(constexpr начиная с C++20)
(условно явный)
template< class Alloc, class... UTypes >
tuple( std::allocator_arg_t, const Alloc& a,
       tuple<UTypes...>&& other );
(20) (начиная с C++11)
(constexpr начиная с C++20)
(условно явный)
template< class Alloc, class... UTypes >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 const tuple<UTypes...>&& other );
(21) (начиная с C++23)
(условно явный)
template< class Alloc, class U1, class U2 >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 std::pair<U1, U2>& p );
(22) (начиная с C++23)
(условно явный)
template< class Alloc, class U1, class U2 >
tuple( std::allocator_arg_t, const Alloc& a,
       const std::pair<U1, U2>& p );
(23) (начиная с C++11)
(constexpr начиная с C++20)
(условно явный)
template< class Alloc, class U1, class U2 >
tuple( std::allocator_arg_t, const Alloc& a,
       std::pair<U1, U2>&& p );
(24) (начиная с C++11)
(constexpr начиная с C++20)
(условно явный)
template< class Alloc, class U1, class U2 >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 const std::pair<U1, U2>&& p );
(25) (начиная с C++23)
(условно явный)
template< class Alloc, tuple-like UTuple >
constexpr tuple( std::allocator_arg_t, const Alloc& a, UTuple&& u );
(26) (начиная с C++23)
(условно явный)
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a,
       const tuple& other );
(27) (начиная с C++11)
(constexpr начиная с C++20)
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a,
       tuple&& other );
(28) (начиная с C++11)
(constexpr начиная с C++20)

Создаёт новый кортеж.

В следующих описаниях пусть

  • i будет находиться в диапазоне [0, sizeof...(Types)) по порядку,
  • Ti будет i-м типом в Types, и
  • Ui будет i-м типом в пакете параметров шаблона с именем UTypes,

где индексация начинается с нуля.

1) Конструктор по умолчанию. Инициализирует значением все элементы, если таковые имеются. Конструктор по умолчанию является тривиальным, если sizeof...(Types) == 0.
  • Эта перегрузка участвует в разрешении перегрузки только если std::is_default_constructible<Ti>::value является true для всех i.
  • Конструктор является explicit тогда и только тогда, когда Ti не может быть инициализирован из списка копирования от {} хотя бы для одного i.
2) Прямой конструктор. Инициализирует каждый элемент кортежа соответствующим параметром.
  • Эта перегрузка участвует в разрешении перегрузки только если sizeof...(Types) >= 1 и std::is_copy_constructible<Ti>::value является true для всех i.
  • Этот конструктор является explicit тогда и только тогда, когда std::is_convertible<const Ti&, Ti>::value является false хотя бы для одного i.
3) Преобразующий конструктор. Инициализирует каждый элемент кортежа соответствующим значением в std::forward<UTypes>(args).
  • Эта перегрузка участвует в разрешении перегрузки только если
    • sizeof...(Types) == sizeof...(UTypes),
    • sizeof...(Types) >= 1,
    • std::is_constructible<Ti, Ui>::value является true для всех i, и
    • пусть D будет std::decay<U0>::type(до C++20)std::remove_cvref_t<U0>(начиная с C++20),
      • если sizeof...(Types) == 1, то D не является std::tuple, в противном случае,
      • если sizeof...(Types) == 2 или sizeof...(Types) == 3, то либо D не является std::allocator_arg_t, либо T0 является std::allocator_arg_t.
  • Конструктор является explicit тогда и только тогда, когда std::is_convertible<Ui, Ti>::value является false хотя бы для одного i.
(начиная с C++23)
4-7) Преобразующий конструктор. Инициализирует каждый элемент кортежа соответствующим элементом из other.

Формально, пусть FWD(other) будет std::forward<decltype(other)>(other), для всех i, инициализирует i-й элемент кортежа с помощью std::get<i>(FWD(other)).

  • Эта перегрузка участвует в разрешении перегрузки только если
    • sizeof...(Types) == sizeof...(UTypes),
    • std::is_constructible_v<Ti, decltype(std::get<i>(FWD(other)))> является true для всех i, и
    • либо
      • sizeof...(Types) не является 1, или
      • (когда Types... разворачивается в T и UTypes... разворачивается в U) std::is_convertible_v<decltype(other), T>, std::is_constructible_v<T, decltype(other)> и std::is_same_v<T, U> все являются false.
  • Эти конструкторы являются explicit тогда и только тогда, когда std::is_convertible_v<decltype(std::get<i>(FWD(other))), Ti> является false хотя бы для одного i.
  • Эти конструкторы определены как удалённые, если инициализация любого элемента, являющегося ссылкой, привязывала бы его к временному объекту.
(начиная с C++23)
8-11) Парный конструктор. Создаёт кортеж из 2 элементов, каждый из которых конструируется из соответствующего элемента p.

Формально, пусть FWD(p) будет std::forward<decltype(p)>(p), инициализирует первый элемен с помощью std::get<0>(FWD(p)) и второй элемент с помощью std::get<1>(FWD(p)).

  • Эта перегрузка участвует в разрешении перегрузки только если
    • sizeof...(Types) == 2,
    • std::is_constructible_v<T0, decltype(std::get<0>(FWD(p)))> является true, и
    • std::is_constructible_v<T1, decltype(std::get<1>(FWD(p)))> является true.
  • Конструктор является explicit тогда и только тогда, когда std::is_convertible_v<decltype(std::get<0>(FWD(p))), T0> или std::is_convertible_v<decltype(std::get<1>(FWD(p))), T1> является false.
  • Эти конструкторы определены как удалённые, если инициализация любого элемента, являющегося ссылкой, привязывала бы его к временному объекту.
(начиная с C++23)
12) tuple-like конструктор. Создаёт кортеж, каждый элемент которого конструируется из соответствующего элемента u.

Формально, для всех i, инициализирует i-й элемент кортежа с помощью std::get<i>(std::forward<UTuple>(u)).

  • Эта перегрузка участвует в разрешении перегрузки только если
    • std::same_as<std::remove_cvref_t<UTuple>, std::tuple> является false,
    • std::remove_cvref_t<UTuple> не является специализацией std::ranges::subrange,
    • sizeof...(Types) равно std::tuple_size_v<std::remove_cvref_t<UTuple>>,
    • std::is_constructible_v<Ti, decltype(std::get<i>(std::forward<UTuple>(u)))> является true для всех i, и
    • либо
      • sizeof...(Types) не является 1, или
      • (когда Types... разворачивается в T) std::is_convertible_v<UTuple, T> и std::is_constructible_v<T, UTuple> оба являются false.
  • Этот конструктор определён как удалённый, если инициализация любого элемента-ссылки привязывала бы его к временному объекту.
13) Неявно определённый конструктор копирования. Инициализирует каждый элемент кортежа соответствующим элементом из other.
  • Этот конструктор является constexpr, если каждая выполняемая им операция является constexpr. Для пустого кортежа std::tuple<> он является constexpr.
  • std::is_copy_constructible<Ti>::value должен быть true для всех i, иначе поведение не определено(до C++20)программа считается некорректной(начиная с C++20).
14) Неявно определённый конструктор перемещения. Для всех i инициализирует i-й элемент кортежа с помощью std::forward<Ui>(std::get<i>(other)).
  • Этот конструктор является constexpr, если каждая выполняемая им операция является constexpr. Для пустого кортежа std::tuple<> он является constexpr.
  • std::is_move_constructible<Ti>::value должен быть true для всех i, иначе поведение не определено(до C++20)эта перегрузка не участвует в разрешении перегрузки(начиная с C++20).
15-28) Идентично (1-14) за исключением того, что каждый элемент создаётся с помощью конструкции с использованием аллокатора, то есть объект Аллокатора a передаётся как дополнительный аргумент конструктору каждого элемента, для которого std::uses_allocator<Ui, Alloc>::value является true.

Параметры

args - значения, используемые для инициализации каждого элемента кортежа
other - кортеж значений, используемых для инициализации каждого элемента кортежа
p - пара значений, используемая для инициализации обоих элементов 2-кортежа
u - tuple-like объект значений, используемый для инициализации каждого элемента кортежа
a - аллокатор, используемый при uses-allocator конструировании

Примечания

Условно-явные конструкторы позволяют создавать кортеж в контексте копирующей инициализации, используя синтаксис списковой инициализации:

std::tuple<int, int> foo_tuple() 
{
    // return {1, -1};             // Ошибка до N4387
    return std::make_tuple(1, -1); // Всегда работает
}

Обратите внимание, что если какой-либо элемент списка не является неявно преобразуемым в соответствующий элемент целевого кортежа, конструкторы становятся явными:

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}); // Ошибка: int не преобразуется неявно в duration
launch_rocket_at(std::tuple<hours, minutes, seconds>{1, 2, 3}); // OK

Пример

#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <vector>
// вспомогательная функция для вывода вектора в поток
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;
}
// вспомогательная функция для вывода кортежа любого размера
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::get<N - 1>(t));
    }
};
template<class Tuple>
struct TuplePrinter<Tuple, 1>
{
    static void print(const Tuple& t)
    {
        print_single(std::get<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";
}
// конец вспомогательной функции
int main()
{
    std::tuple<int, std::string, double> t1;
    print("Инициализированное значением, t1:", t1);
    std::tuple<int, std::string, double> t2{42, "Тест", -3,14};
    print("Инициализировано со значениями, t2:", t2);
    std::tuple<char, std::string, int> t3{t2};
    print("Неявно преобразовано, t3:", t3);
    std::tuple<int, double> t4{std::make_pair(42, 3,14)};
    print("Сконструировано из пары, t4:", t4);
    // дан Allocator my_alloc с однопараметрическим конструктором
    // my_alloc(int); используйте my_alloc(1) для выделения 5 целых чисел в векторе
    using my_alloc = std::allocator<int>;
    std::vector<int, my_alloc> v{5, 1, my_alloc{/* 1 */}};
    // использование my_alloc(2) для выделения 5 целых чисел в векторе внутри кортежа
    std::tuple<int, std::vector<int, my_alloc>, double> t5
        {std::allocator_arg, my_alloc{/* 2 */}, 42, v, -3,14};
    print("Сконструировано с аллокатором, t5:", t5);
}

Возможный вывод:

Инициализированное значением по умолчанию, t1: (0, "", 0)
Инициализировано значениями, t2: (42, "Test", -3.14)
Неявно преобразовано, t3: ('*', "Test", -3)
Сконструировано из пары, t4: (42, 3.14)
Сконструировано с аллокатором, t5: (42, {1,1,1,1,1}, -3.14)

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применяется к Поведение в опубликованной версии Корректное поведение
LWG 2510 C++11 конструктор по умолчанию был неявным сделан условно-явным
LWG 3121 C++11 конструктор 1-кортежа мог рекурсивно проверять ограничения;
allocator_arg_t аргумент вызывал неоднозначность
дополнительно ограничен
конструктор
LWG 3158 C++11 конструктор с использованием аллокатора, соответствующий
конструктору по умолчанию, был неявным
сделан условно-явным
LWG 3211 C++11 является ли конструктор по умолчанию
tuple<> тривиальным, не было указано
требуется быть тривиальным
LWG 4045 C++23 tuple-like конструктор может потенциально создавать висячие ссылки определен как удаленный
N4387 C++11 некоторые конструкторы были явными, что препятствовало полезному поведению большинство конструкторов сделано
условно-явными

Смотрите также

присваивает содержимое одного tuple другому
(public member function)
(C++11)
создаёт объект tuple типа, определённого типами аргументов
(function template)
(C++11)
создаёт tuple ссылок на lvalue или распаковывает tuple в отдельные объекты
(function template)
создаёт tuple из forwarding references
(function template)
создаёт новый pair
(public member function of std::pair<T1,T2> )