Пространства имён
Варианты
Действия

std::tuple::tuple

Материал из cppreference.com
 
 
Библиотека утилит
Языковая поддержка
Поддержка типов (базовые типы, RTTI)
Макросы тестирования функциональности библиотеки (C++20)    
Управление динамической памятью
Программные утилиты
Поддержка сопрограмм (C++20)
Вариативные функции
Трёхстороннее сравнение (C++20)
(C++20)
(C++20)(C++20)(C++20)(C++20)(C++20)(C++20)
Общие утилиты
Дата и время
Функциональные объекты
Библиотека форматирования (C++20)
(C++11)
Операторы отношения (устарело в C++20)
Целочисленные функции сравнения
(C++20)(C++20)(C++20)    
(C++20)
Операции обмена и типа
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Общие лексические типы
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
Элементарные преобразования строк
(C++17)
(C++17)
 
 
<tbody> </tbody>
Определено в заголовочном файле <tuple>
constexpr tuple();
(1) (начиная с C++11)
(conditionally explicit)
tuple( const Types&... args );
(2) (начиная с C++11)
(constexpr since C++14)
(conditionally explicit)
template< class... UTypes > tuple( UTypes&&... args );
(3) (начиная с C++11)
(constexpr since C++14)
(conditionally explicit)
template< class... UTypes > constexpr tuple( tuple<UTypes...>& other );
(4) (начиная с C++23)
(conditionally explicit)
template< class... UTypes > tuple( const tuple<UTypes...>& other );
(5) (начиная с C++11)
(constexpr since C++14)
(conditionally explicit)
template< class... UTypes > tuple( tuple<UTypes...>&& other );
(6) (начиная с C++11)
(constexpr since C++14)
(conditionally explicit)
template< class... UTypes > constexpr tuple( const tuple<UTypes...>&& other );
(7) (начиная с C++23)
(conditionally explicit)
template< class U1, class U2 > constexpr tuple( std::pair<U1, U2>& p );
(8) (начиная с C++23)
(conditionally explicit)
template< class U1, class U2 > tuple( const std::pair<U1, U2>& p );
(9) (начиная с C++11)
(constexpr since C++14)
(conditionally explicit)
template< class U1, class U2 > tuple( std::pair<U1, U2>&& p );
(10) (начиная с C++11)
(constexpr since C++14)
(conditionally explicit)
template< class U1, class U2 > constexpr tuple( const std::pair<U1, U2>&& p );
(11) (начиная с C++23)
(conditionally explicit)
template< tuple-like UTuple > constexpr tuple( UTuple&& u );
(12) (начиная с C++23)
(conditionally explicit)
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 since C++20)
(conditionally explicit)
template< class Alloc > tuple( std::allocator_arg_t, const Alloc& a, const Types&... args );
(16) (начиная с C++11)
(constexpr since C++20)
(conditionally explicit)
template< class Alloc, class... UTypes > tuple( std::allocator_arg_t, const Alloc& a, UTypes&&... args );
(17) (начиная с C++11)
(constexpr since C++20)
(conditionally explicit)
template< class Alloc, class... UTypes > constexpr tuple( std::allocator_arg_t, const Alloc& a, tuple<UTypes...>& other );
(18) (начиная с C++23)
(conditionally explicit)
template< class Alloc, class... UTypes > tuple( std::allocator_arg_t, const Alloc& a, const tuple<UTypes...>& other );
(19) (начиная с C++11)
(constexpr since C++20)
(conditionally explicit)
template< class Alloc, class... UTypes > tuple( std::allocator_arg_t, const Alloc& a, tuple<UTypes...>&& other );
(20) (начиная с C++11)
(constexpr since C++20)
(conditionally explicit)
template< class Alloc, class... UTypes > constexpr tuple( std::allocator_arg_t, const Alloc& a, const tuple<UTypes...>&& other );
(21) (начиная с C++23)
(conditionally explicit)
template< class Alloc, class U1, class U2 > constexpr tuple( std::allocator_arg_t, const Alloc& a, std::pair<U1, U2>& p );
(22) (начиная с C++23)
(conditionally explicit)
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 since C++20)
(conditionally explicit)
template< class Alloc, class U1, class U2 > tuple( std::allocator_arg_t, const Alloc& a, std::pair<U1, U2>&& p );
(24) (начиная с C++11)
(constexpr since C++20)
(conditionally explicit)
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)
(conditionally explicit)
template< class Alloc, tuple-like UTuple > constexpr tuple( std::allocator_arg_t, const Alloc& a, UTuple&& u );
(26) (начиная с C++23)
(conditionally explicit)
template< class Alloc > tuple( std::allocator_arg_t, const Alloc& a, const tuple& other );
(27) (начиная с C++11)
(constexpr since C++20)
template< class Alloc > tuple( std::allocator_arg_t, const Alloc& a, tuple&& other );
(28) (начиная с C++11)
(constexpr since C++20)

Создаёт новый tuple.

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

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

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

1) Конструктор по умолчанию. Инициализирует значением все элементы, если таковые имеются. Конструктор по умолчанию тривиален, если sizeof...(Types) == 0.
  • Эта перегрузка участвует в разрешении перегрузки, только если std::is_default_constructible<Ti>::value равно true для всех i
  • Конструктор является explicit тогда и только тогда, когда Ti не является инициализируемым копированием списка из {} хотя бы для одного i.
2) Прямой конструктор. Инициализирует каждый элемент tuple соответствующим параметром.
  • Эта перегрузка участвует в разрешении перегрузки, только если sizeof...(Types) >= 1 и std::is_copy_constructible<Ti>::value равно true для всех i.
  • Этот конструктор является explicit тогда и только тогда, когда std::is_convertible<const Ti&, Ti>::value равно false хотя бы для одного i.
3) Преобразующий конструктор. Инициализирует каждый элемент tuple соответствующим значением в 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) Преобразующий конструктор преобразования. Инициализирует каждый элемент tuple соответствующим элементом 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) Конструктор парного копирования. Создаёт двухэлементный tuple, каждый элемент которого состоит из соответствующего элемента 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. Создаёт кортеж, каждый элемент которого состоит из соответствующего элементаf 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) за исключением того, что каждый элемент создаётся конструирования, использующего аллокатор, то есть объект Allocator a передаётся в качестве дополнительного аргумента в конструктор каждого элемента, для которого std::uses_allocator<Ui, Alloc>::value равно true.

Параметры

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

Примечание

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

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

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

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 нельзя неявно преобразовать в длительность
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;
}

// вспомогательная функция для печати tuple любого размера
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("Создание из pair, t4: ", t4);

    // заданный Аллокатор 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 целых чисел в векторе в tuple
    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)
Создание из pair, t4: (42, 3.14)
Создание с аллокатором, t5: (42, {1,1,1,1,1}, -3.14)

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

Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:

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

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

присваивает содержимое одного tuple другому
(public функция-элемент) [править]
создаёт объект tuple типа, определённого типами аргументов
(шаблон функции) [править]
создаёт std::tuple левосторонних ссылок или распаковывает кортеж на отдельные объекты
(шаблон функции) [править]
создаёт tuple пересылалаемых ссылок
(шаблон функции) [править]
создаёт новый pair
(public функция-элемент std::pair) [править]