std::tuple::tuple
| Определено в заголовочном файле <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находиться в диапазоне[0,sizeof...(Types))по порядку,Tiбудетi-м типом вTypes, иUiбудетi-м типом в пакете параметров шаблона с именемUTypes,
где индексация начинается с нуля.
sizeof...(Types) == 0.
- Эта перегрузка участвует в разрешении перегрузки, только если
std::is_default_constructible<Ti>::valueравноtrueдля всехi - Конструктор является
explicitтогда и только тогда, когдаTiне является инициализируемым копированием списка из{}хотя бы для одногоi.
- Эта перегрузка участвует в разрешении перегрузки, только если
sizeof...(Types) >= 1иstd::is_copy_constructible<Ti>::valueравноtrueдля всехi. - Этот конструктор является
explicitтогда и только тогда, когдаstd::is_convertible<const Ti&, Ti>::valueравноfalseхотя бы для одногоi.
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) |
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) |
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) |
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.
other.
- Этот конструктор является
constexpr, если каждая выполняемая им операция являетсяconstexpr. Для пустого кортежаstd::tuple<>, этоconstexpr. std::is_copy_constructible<Ti>::valueдолжно бытьtrueдля всехi, иначе поведение не определено (до C++20)программа некорректна (начиная с C++20).
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).
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 функция-элемент) | |
(C++11) |
создаёт объект tuple типа, определённого типами аргументов (шаблон функции) |
| создаёт std::tuple левосторонних ссылок или распаковывает кортеж на отдельные объекты (шаблон функции) | |
(C++11) |
создаёт tuple пересылалаемых ссылок (шаблон функции) |
| создаёт новый pair (public функция-элемент std::pair)
|