std::tuple<Types...>::tuple

From cppreference.com
< cpp‎ | utility‎ | tuple
 
 
 
 
Defined in header <tuple>
constexpr tuple();
(1) (since C++11)
(conditionally explicit)
tuple( const Types&... args );
(2) (since C++11)
(constexpr since C++14)
(conditionally explicit)
template< class... UTypes >
tuple( UTypes&&... args );
(3) (since C++11)
(constexpr since C++14)
(conditionally explicit)
template< class... UTypes >
tuple( const tuple<UTypes...>& other );
(4) (since C++11)
(constexpr since C++14)
(conditionally explicit)
template <class... UTypes>
tuple( tuple<UTypes...>&& other );
(5) (since C++11)
(constexpr since C++14)
(conditionally explicit)
template< class U1, class U2 >
tuple( const pair<U1,U2>& p );
(6) (since C++11)
(constexpr since C++14)
(conditionally explicit)
template< class U1, class U2 >
tuple( pair<U1,U2>&& p );
(7) (since C++11)
(constexpr since C++14)
(conditionally explicit)
tuple( const tuple& other ) = default;
(8) (since C++11)
tuple( tuple&& other ) = default;
(9) (since C++11)
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a );
(10) (since C++11)
(constexpr since C++20)
template< class Alloc >

tuple( std::allocator_arg_t, const Alloc& a,

       const Types&... args );
(11) (since C++11)
(constexpr since C++20)
(conditionally explicit)
template< class Alloc, class... UTypes >

tuple( std::allocator_arg_t, const Alloc& a,

       UTypes&&... args );
(12) (since C++11)
(constexpr since C++20)
(conditionally explicit)
template <class Alloc, class... UTypes>

tuple( std::allocator_arg_t, const Alloc& a,

       const tuple<UTypes...>& other );
(13) (since C++11)
(constexpr since C++20)
(conditionally explicit)
template< class Alloc, class... UTypes >

tuple( std::allocator_arg_t, const Alloc& a,

       tuple<UTypes...>&& other );
(14) (since C++11)
(constexpr since C++20)
(conditionally explicit)
template< class Alloc, class U1, class U2 >

tuple( std::allocator_arg_t, const Alloc& a,

       const pair<U1, U2>& p );
(15) (since C++11)
(constexpr since C++20)
(conditionally explicit)
template< class Alloc, class U1, class U2 >

tuple( std::allocator_arg_t, const Alloc& a,

       pair<U1, U2>&& p );
(16) (since C++11)
(constexpr since C++20)
(conditionally explicit)
template< class Alloc >

tuple( std::allocator_arg_t, const Alloc& a,

       const tuple& other );
(17) (since C++11)
(constexpr since C++20)
template< class Alloc >

tuple( std::allocator_arg_t, const Alloc& a,

       tuple&& other );
(18) (since C++11)
(constexpr since C++20)

Constructs a new tuple.

1) Default constructor. Value-initializes all elements.
This overload only participates in overload resolution if std::is_default_constructible<Ti>::value is true for all i
The constructor is explicit if and only if Ti is not implicitly default-constructible for at least one i.
2) Direct constructor. Initializes each element of the tuple with the corresponding parameter.
This overload only participates in overload resolution 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 only participates in overload resolution if sizeof...(Types) == sizeof...(UTypes) and sizeof...(Types) >= 1 and std::is_constructible<Ti, Ui&&>::value is true for all i.
The constructor is explicit if and only if std::is_convertible<Ui&&, Ti>::value is false for at least one i.
4) Converting copy-constructor. For all i in sizeof...(UTypes), initializes ith element of the tuple with std::get<i>(other).
This overload only participates in overload resolution if

sizeof...(Types) == sizeof...(UTypes) and
std::is_constructible_v<Ti, const Ui&> is true for all i and
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<const Ui&, Ti>::value is false for at least one i.
5) 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 only participates in overload resolution if

sizeof...(Types) == sizeof...(UTypes) and
std::is_constructible_v<Ti, Ui&&> is true for all i and
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<Ui&&, Ti>::value is false for at least one i.
6) 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 only participates in overload resolution 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.
7) 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 only participates in overload resolution 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::convertible<U2&&, T1>::value is false.
8) 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.
Requires that std::is_copy_constructible<Ti>::value is true for all i.
9) 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.
Requires that std::is_move_constructible<Ti>::value is true for all i.
10-18) Identical to (1-9) 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 - a tuple of values used to initialize each element of the tuple
p - pair of values used to initialize both elements of this 2-tuple
a - 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

Defect reports

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

DR Applied to Behavior as published Correct behavior
N4387 C++11 some constructors were explicit, preventing useful behavior most constructors made conditionally-explicit
LWG 2510 C++11 default constructor was implicit made conditionally-explicit

Example

#include <iostream>
#include <string>
#include <vector>
#include <tuple>
#include <memory>
 
// 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 << ", " << std::get<N-1>(t);
    }
};
 
template<class Tuple>
struct TuplePrinter<Tuple, 1>{
    static void print(const Tuple& t) 
    {
        std::cout << 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: "; print(t1);
    std::tuple<int, std::string, double> t2(42, "Test", -3.14);
    std::cout << "Initialized with values: "; print(t2);
    std::tuple<char, std::string, int> t3(t2);
    std::cout << "Implicitly converted: "; print(t3);
    std::tuple<int, double> t4(std::make_pair(42, 3.14));
    std::cout << "Constructed from a pair"; print(t4);
 
    // given Allocator my_alloc with a single-argument constructor my_alloc(int)
    // use my_alloc(1) to allocate 10 ints in a vector
    std::vector<int, my_alloc> v(10, 1, my_alloc(1));
    // use my_alloc(2) to allocate 10 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);
}

Possible output:

Value-initialized: (0, , 0)
Initialized with values: (42, Test, -3.14)
Implicitly converted: (*, Test, -3)
Constructed from a pair(42, 3.14)

See also

creates a tuple object of the type defined by the argument types
(function template)
creates a tuple of lvalue references or unpacks a tuple into individual objects
(function template)
creates a tuple of rvalue references
(function template)