std::tuple<Types...>::tuple
| Определено в заголовке <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,
где индексация начинается с нуля.
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 конструктор. Создаёт кортеж, каждый элемент которого конструируется из соответствующего элемента 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 | - | значения, используемые для инициализации каждого элемента кортежа |
| 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) |
|
(C++11)
|
создаёт
tuple
из
forwarding references
(function template) |
создаёт новый
pair
(public member function of
std::pair<T1,T2>
)
|