Scroll to navigation

std::tuple::tuple(3) C++ Standard Libary std::tuple::tuple(3)

NAME

std::tuple::tuple - std::tuple::tuple

Synopsis


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)
template< tuple-like UTuple > (12) (since C++23)
constexpr tuple( UTuple&& u ); (conditionally explicit)
tuple( const tuple& other ) = default; (13) (since C++11)
tuple( tuple&& other ) = default; (14) (since C++11)
Allocator-extended constructors
template< class Alloc > (since C++11)
tuple( std::allocator_arg_t, const Alloc& a ); (15) (constexpr since C++20)
(conditionally explicit)
template< class Alloc >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (16) (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, (17) (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, (18) (conditionally explicit)


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)
const tuple<UTypes...>& other );
template< class Alloc, class... UTypes >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (20) (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, (21) (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, (22) (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, (23) (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, (24) (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, (25) (conditionally explicit)


const std::pair<U1, U2>&& p );
template< class Alloc, tuple-like UTuple > (since C++23)
constexpr tuple( std::allocator_arg_t, const Alloc& a, (26) (conditionally explicit)
UTuple&& u );
template< class Alloc >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (27) (constexpr since C++20)


const tuple& other );
template< class Alloc >
(since C++11)
tuple( std::allocator_arg_t, const Alloc& a, (28) (constexpr since C++20)


tuple&& other );


Constructs a new tuple.


In the descriptions that follow, let


* i be in the range [0, sizeof...(Types)) in order,
* Ti be the ith type in Types, and
* Ui be the ith type in a template parameter pack named UTypes,


where indexing is zero-based.


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),
* sizeof...(Types) >= 1,
* 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 std::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-7) Converting constructor. Initializes each element of the tuple with the
corresponding element of other.


Formally, let FWD(other) be std::forward<decltype(other)>(other), for all i,
initializes ith element of the tuple with std::get<i>(FWD(other)).


* This overload participates in overload resolution only if
* sizeof...(Types) == sizeof...(UTypes),
* std::is_constructible_v<Ti, decltype(std::get<i>(FWD(other)))> is true for
all i, and
* either
* sizeof...(Types) is not 1, or
* (when Types... expands to T and UTypes... expands to U)
std::is_convertible_v<decltype(other), T>, std::is_constructible_v<T,
decltype(other)>, and std::is_same_v<T, U> are all false.
* These constructors are explicit if and only if
std::is_convertible_v<decltype(std::get<i>(FWD(other))), Ti> is false for at
least one i.


* These constructors are defined as deleted if the initialization of
any element that is a reference would bind it to a temporary (since C++23)
object.


8-11) Pair constructor. Constructs a 2-element tuple with each element constructed
from the corresponding element of p.


Formally, let FWD(p) be std::forward<decltype(p)>(p), initializes the first element
with std::get<0>(FWD(p)) and the second element with std::get<1>(FWD(p)).


* This overload participates in overload resolution only if
* sizeof...(Types) == 2,
* std::is_constructible_v<T0, decltype(std::get<0>(FWD(p)))> is true, and
* std::is_constructible_v<T1, decltype(std::get<1>(FWD(p)))> is true.
* The constructor is explicit if and only if
std::is_convertible_v<decltype(std::get<0>(FWD(p))), T0> or
std::is_convertible_v<decltype(std::get<1>(FWD(p))), T1> is false.


* These constructors are defined as deleted if the initialization of
any element that is a reference would bind it to a temporary (since C++23)
object.


12) tuple-like constructor. Constructs a tuple with each element constructed from
the corresponding element of u.


Formally, for all i, initializes ith element of the tuple with
std::get<i>(std::forward<UTuple>(u)).


* This overload participates in overload resolution only if
* std::same_as<std::remove_cvref_t<UTuple>, std::tuple> is false,
* std::remove_cvref_t<UTuple> is not a specialization of
std::ranges::subrange,
* sizeof...(Types) equals std::tuple_size_v<std::remove_cvref_t<UTuple>>,
* std::is_constructible_v<Ti, decltype(std::get<i>(std::forward<UTuple>(u)))>
is true for all i, and
* either
* sizeof...(Types) is not 1, or
* (when Types... expands to T) std::is_convertible_v<UTuple, T> and
std::is_constructible_v<T, UTuple> are both false.
* This constructor is defined as deleted if the initialization of any element that
is a reference would bind it to a temporary object.
13) 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).
14) Implicitly-defined move constructor. For all i, initializes the 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).
15-28) Identical to (1-14) 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.

Parameters


args - values used to initialize each element of the tuple
other - the tuple of values used to initialize each element of the tuple
p - the pair of values used to initialize both elements of the 2-tuple
u - the tuple-like object of values used to initialize each element of the tuple
a - the allocator to use in uses-allocator construction

Notes


Conditionally-explicit constructors make it possible to construct a tuple in
copy-initialization context using list-initialization syntax:


std::tuple<int, int> foo_tuple()
{
// return {1, -1}; // Error before N4387
return std::make_tuple(1, -1); // Always works
}


Note that if some element of the list is not implicitly convertible to the
corresponding element of the target tuple, the constructors become explicit:


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}); // Error: int is not implicitly convertible to duration
launch_rocket_at(std::tuple<hours, minutes, seconds>{1, 2, 3}); // OK

Example

// Run this code


#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#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(std::string_view message, const std::tuple<Args...>& t)
{
std::cout << message << " (";
TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
std::cout << ")\n";
}
// end helper function


int main()
{
std::tuple<int, std::string, double> t1;
print("Value-initialized, t1:", t1);


std::tuple<int, std::string, double> t2{42, "Test", -3.14};
print("Initialized with values, t2:", t2);


std::tuple<char, std::string, int> t3{t2};
print("Implicitly converted, t3:", t3);


std::tuple<int, double> t4{std::make_pair(42, 3.14)};
print("Constructed from a pair, t4:", 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};
print("Constructed with allocator, t5:", t5);
}

Possible output:


Value-initialized, t1: (0, "", 0)
Initialized with values, t2: (42, "Test", -3.14)
Implicitly converted, t3: ('*', "Test", -3)
Constructed from a pair, t4: (42, 3.14)
Constructed with allocator, t5: (42, {1,1,1,1,1}, -3.14)


Defect reports


The following behavior-changing defect reports were applied retroactively to
previously published C++ standards.


DR Applied to Behavior as published Correct behavior
LWG 2510 C++11 default constructor was implicit made conditionally-explicit
constructor of 1-tuple might
LWG 3121 C++11 recursively check the constraints; furtherly constrained
allocator_arg_t argument brought the constructor
ambiguity
the uses-allocator constructor
LWG 3158 C++11 corresponding made conditionally-explicit
to default constructor was implicit
LWG 3211 C++11 whether the default constructor of require to be trivial
tuple<> is trivial was unspecified
N4387 C++11 some constructors were explicit, most constructors made
preventing useful behavior conditionally-explicit
tuple-like constructor may
LWG 4045 C++23 potentially create dangling made defined as deleted
references

See also


operator= assigns the contents of one tuple to another
(public member function)
make_tuple creates a tuple object of the type defined by the argument types
(C++11) (function template)
tie creates a tuple of lvalue references or unpacks a tuple into
(C++11) individual objects
(function template)
forward_as_tuple creates a tuple of forwarding references
(C++11) (function template)
constructor constructs new pair
(public member function of std::pair<T1,T2>)

2024.06.10 http://cppreference.com