Defined in header <tuple>
constexpr tuple(); (1) (since C++11)
(conditionally explicit)
(since C++11)
tuple( const Types&... args ); (2) (constexpr since C++14)
(conditionally explicit)
template< class... UTypes > (since C++11)
tuple( UTypes&&... args ); (3) (constexpr since C++14)
(conditionally explicit)
template< class... UTypes > (4) (since C++23)
constexpr tuple( tuple<UTypes...>& other ); (conditionally
explicit)
template< class... UTypes > (since C++11)
tuple( const tuple<UTypes...>& other ); (5) (constexpr since
C++14)
(conditionally explicit)
template< class... UTypes > (since C++11)
tuple( tuple<UTypes...>&& other ); (6) (constexpr since
C++14)
(conditionally explicit)
template< class... UTypes > (7) (since C++23)
constexpr tuple( const tuple<UTypes...>&& other );
(conditionally explicit)
template< class U1, class U2 > (8) (since C++23)
constexpr tuple( std::pair<U1, U2>& p ); (conditionally explicit)
template< class U1, class U2 > (since C++11)
tuple( const std::pair<U1, U2>& p ); (9) (constexpr since
C++14)
(conditionally explicit)
template< class U1, class U2 > (since C++11)
tuple( std::pair<U1, U2>&& p ); (10) (constexpr since
C++14)
(conditionally explicit)
template< class U1, class U2 > (11) (since C++23)
constexpr tuple( const std::pair<U1, U2>&& p ); (conditionally
explicit)
tuple( const tuple& other ) = default; (12) (since C++11)
tuple( tuple&& other ) = default; (13) (since C++11)
template< class Alloc > (since C++11)
tuple( std::allocator_arg_t, const Alloc& a ); (14) (constexpr
since C++20)
(conditionally explicit)
template< class Alloc >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (15) (constexpr since
C++20)
(conditionally explicit)
const Types&... args );
template< class Alloc, class... UTypes >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (16) (constexpr since
C++20)
(conditionally explicit)
UTypes&&... args );
template< class Alloc, class... UTypes >
(since C++23)
constexpr tuple( std::allocator_arg_t, const Alloc& a, (17)
(conditionally explicit)
tuple<UTypes...>& other );
template< class Alloc, class... UTypes >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (18) (constexpr since
C++20)
(conditionally explicit)
const tuple<UTypes...>& other );
template< class Alloc, class... UTypes >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (19) (constexpr since
C++20)
(conditionally explicit)
tuple<UTypes...>&& other );
template< class Alloc, class... UTypes >
(since C++23)
constexpr tuple( std::allocator_arg_t, const Alloc& a, (20)
(conditionally explicit)
const tuple<UTypes...>&& other );
template< class Alloc, class U1, class U2 >
(since C++23)
constexpr tuple( std::allocator_arg_t, const Alloc& a, (21)
(conditionally explicit)
std::pair<U1, U2>& p );
template< class Alloc, class U1, class U2 >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (22) (constexpr since
C++20)
(conditionally explicit)
const std::pair<U1, U2>& p );
template< class Alloc, class U1, class U2 >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (23) (constexpr since
C++20)
(conditionally explicit)
std::pair<U1, U2>&& p );
template< class Alloc, class U1, class U2 >
(since C++23)
constexpr tuple( std::allocator_arg_t, const Alloc& a, (24)
(conditionally explicit)
const std::pair<U1, U2>&& p );
template< class Alloc >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (25) (constexpr since
C++20)
const tuple& other );
template< class Alloc >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (26) (constexpr since
C++20)
tuple&& other );
Constructs a new tuple.
1) Default constructor. Value-initializes all elements, if any. The default
constructor is trivial if sizeof...(Types) == 0.
* This overload participates in overload resolution only if
std::is_default_constructible<Ti>::value is true for all i
* The constructor is explicit if and only if Ti is not
copy-list-initializable
from {} for at least one i.
2) Direct constructor. Initializes each element of the tuple with the
corresponding
parameter.
* This overload participates in overload resolution only if sizeof...(Types)
>= 1
and std::is_copy_constructible<Ti>::value is true for all i.
* This constructor is explicit if and only if std::is_convertible<const
Ti&,
Ti>::value is false for at least one i.
3) Converting constructor. Initializes each element of the tuple with the
corresponding value in std::forward<UTypes>(args).
* This overload participates in overload resolution only if
* sizeof...(Types) == sizeof...(UTypes), and
* sizeof...(Types) >= 1, and
* std::is_constructible<Ti, Ui>::value is true for all i, and
* let D be
std::decay<U0>::type
(until C++20)
std::remove_cvref_t<U0>
(since C++20),
* if sizeof...(Types) == 1, then D is not tuple, otherwise,
* if sizeof...(Types) == 2 or sizeof...(Types) == 3, then either D is
not std::allocator_arg_t, or T0 is std::allocator_arg_t.
* The constructor is explicit if and only if std::is_convertible<Ui,
Ti>::value is
false for at least one i.
* This constructor is defined as deleted if the initialization of
any element that is a reference would bind it to a temporary (since C++23)
object.
4) Converting copy-constructor. For all i in sizeof...(UTypes), initializes
ith
element of the tuple with std::get<i>(other).
* This overload participates in overload resolution only if
* sizeof...(Types) == sizeof...(UTypes) and
* std::is_constructible_v<Ti, Ui&> is true for all i and
* either
* sizeof...(Types) != 1 or
* (when Types... expands to T and UTypes... expands to U)
std::is_convertible_v<tuple<U>&, T>,
std::is_constructible_v<T,
tuple<U>&>, and std::is_same_v<T, U> are all false.
* The constructor is explicit if and only if
std::is_convertible_v<Ui&, Ti> is
false for at least one i.
* This constructor is defined as deleted if the initialization of any element
that
is a reference would bind it to a temporary object.
5) Converting copy-constructor. For all i in sizeof...(UTypes), initializes
ith
element of the tuple with std::get<i>(other).
* This overload participates in overload resolution only if
* sizeof...(Types) == sizeof...(UTypes) and
* std::is_constructible<Ti, const Ui&>::value is true for all i and
* either
* sizeof...(Types) != 1 or
* (when Types... expands to T and UTypes... expands to U)
std::is_convertible<const tuple<U>&, T>::value,
std::is_constructible<T, const tuple<U>&>::value, and
std::is_same<T,
U>::value are all false.
* The constructor is explicit if and only if std::is_convertible<const
Ui&,
Ti>::value is false for at least one i.
* This constructor is defined as deleted if the initialization of
any element that is a reference would bind it to a temporary (since C++23)
object.
6) Converting move-constructor. For all i in sizeof...(UTypes), initializes
ith
element of the tuple with
std::forward<Ui>(std::get<i>(other)).
* This overload participates in overload resolution only if
* sizeof...(Types) == sizeof...(UTypes) and
* std::is_constructible<Ti, Ui>::value is true for all i and
* either
* sizeof...(Types) != 1 or
* (when Types... expands to T and UTypes... expands to U)
std::is_convertible<tuple<U>, T>::value,
std::is_constructible<T,
tuple<U>>::value, and std::is_same<T, U>::value are all
false.
* The constructor is explicit if and only if std::is_convertible<Ui,
Ti>::value is
false for at least one i.
* This constructor is defined as deleted if the initialization of
any element that is a reference would bind it to a temporary (since C++23)
object.
7) Converting move-constructor. For all i in sizeof...(UTypes), initializes
ith
element of the tuple with std::forward<const
Ui>(std::get<i>(other)).
* This overload participates in overload resolution only if
* sizeof...(Types) == sizeof...(UTypes) and
* std::is_constructible_v<Ti, const Ui> is true for all i and
* either
* sizeof...(Types) != 1 or
* (when Types... expands to T and UTypes... expands to U)
std::is_convertible_v<const tuple<U>, T>,
std::is_constructible_v<T,
const tuple<U>>, and std::is_same_v<T, U> are all false.
* The constructor is explicit if and only if std::is_convertible_v<const
Ui, Ti>
is false for at least one i.
* This constructor is defined as deleted if the initialization of any element
that
is a reference would bind it to a temporary object.
8) Pair copy constructor. Constructs a 2-element tuple with the first element
constructed from p.first and the second element from p.second
* This overload participates in overload resolution only if sizeof...(Types)
== 2
and std::is_constructible_v<T0, U1&> and
std::is_constructible_v<T1, U2&> are
both true
* The constructor is explicit if and only if
std::is_convertible_v<U1&, T0> or
std::is_convertible_v<U2&, T1> is false.
* This constructor is defined as deleted if the initialization of any element
that
is a reference would bind it to a temporary object.
9) Pair copy constructor. Constructs a 2-element tuple with the first element
constructed from p.first and the second element from p.second
* This overload participates in overload resolution only if sizeof...(Types)
== 2
and std::is_constructible<T0,const U1&>::value and
std::is_constructible<T1,
const U2&>::value are both true
* The constructor is explicit if and only if std::is_convertible<const
U1&,
T0>::value or std::is_convertible<const U2&, T1>::value is
false.
* This constructor is defined as deleted if the initialization of
any element that is a reference would bind it to a temporary (since C++23)
object.
10) Pair move constructor. Constructs a 2-element tuple with the first
element
constructed from std::forward<U1>(p.first) and the second element from
std::forward<U2>(p.second)
* This overload participates in overload resolution only if sizeof...(Types)
== 2
and std::is_constructible<T0, U1>::value and
std::is_constructible<T1,
U2>::value are both true
* The constructor is explicit if and only if std::is_convertible<U1,
T0>::value or
std::is_convertible<U2, T1>::value is false.
* This constructor is defined as deleted if the initialization of
any element that is a reference would bind it to a temporary (since C++23)
object.
11) Pair move constructor. Constructs a 2-element tuple with the first
element
constructed from std::forward<const U1>(p.first) and the second element
from
std::forward<const U2>(p.second)
* This overload participates in overload resolution only if sizeof...(Types)
== 2
and std::is_constructible_v<T0, const U1> and
std::is_constructible_v<T1, const
U2> are both true
* The constructor is explicit if and only if std::is_convertible_v<U1,
T0> or
std::is_convertible_v<U2, T1> is false.
* This constructor is defined as deleted if the initialization of any element
that
is a reference would bind it to a temporary object.
12) Implicitly-defined copy constructor. Initializes each element of the
tuple with
the corresponding element of other.
* This constructor is constexpr if every operation it performs is constexpr.
For
the empty tuple std::tuple<>, it is constexpr.
* std::is_copy_constructible<Ti>::value must be true for all i,
otherwise
the behavior is undefined
(until C++20)
the program is ill-formed
(since C++20).
13) Implicitly-defined move constructor. Initializes each ith element of the
tuple
with std::forward<Ui>(std::get<i>(other)).
* This constructor is constexpr if every operation it performs is constexpr.
For
the empty tuple std::tuple<>, it is constexpr.
* std::is_move_constructible<Ti>::value must be true for all i,
otherwise
the behavior is undefined
(until C++20)
this overload does not participate in overload resolution
(since C++20).
14-26) Identical to (1-13) except each element is created by uses-allocator
construction, that is, the Allocator object a is passed as an additional
argument to
the constructor of each element for which std::uses_allocator<Ui,
Alloc>::value is
true.
// Run this code
#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
#include <tuple>
#include <type_traits>
#include <vector>
// helper function to print a vector to a stream
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;
}
// helper function to print a tuple of any size
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(const std::tuple<Args...>& t)
{
std::cout << "(";
TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
std::cout << ")\n";
}
// end helper function
int main()
{
std::tuple<int, std::string, double> t1;
std::cout << "Value-initialized, t1: "; print(t1);
std::tuple<int, std::string, double> t2{42, "Test", -3.14};
std::cout << "Initialized with values, t2: "; print(t2);
std::tuple<char, std::string, int> t3{t2};
std::cout << "Implicitly converted, t3: "; print(t3);
std::tuple<int, double> t4{std::make_pair(42, 3.14)};
std::cout << "Constructed from a pair, t4: "; print(t4);
// given Allocator my_alloc with a single-argument constructor
// my_alloc(int); use my_alloc(1) to allocate 5 ints in a vector
using my_alloc = std::allocator<int>;
std::vector<int, my_alloc> v { 5, 1, my_alloc{/*1*/} };
// use my_alloc(2) to allocate 5 ints in a vector in a tuple
std::tuple<int, std::vector<int, my_alloc>, double> t5{
std::allocator_arg, my_alloc{/*2*/}, 42, v, -3.14};
std::cout << "Constructed with allocator, t5: "; print(t5);
}