Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/utility/tuple/operator="

From cppreference.com
< cpp‎ | utility‎ | tuple
m (Example: simplified the printing.)
m (Synopsis: ~(constexpr since C++20).)
 
Line 2: Line 2:
 
{{cpp/utility/tuple/navbar}}
 
{{cpp/utility/tuple/navbar}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl rev multi|num=1|since1=c++11|dcl1=
+
{{dcla|num=1|since=c++11|constexpr=c++20|1=
 
tuple& operator=( const tuple& other );
 
tuple& operator=( const tuple& other );
|since2=c++20|dcl2=
 
constexpr tuple& operator=( const tuple& other );
 
 
}}
 
}}
 
{{dcl|num=2|since=c++23|1=
 
{{dcl|num=2|since=c++23|1=
 
constexpr const tuple& operator=( const tuple& other ) const;
 
constexpr const tuple& operator=( const tuple& other ) const;
 
}}
 
}}
{{dcl rev multi|num=3|since1=c++11|dcl1=
+
{{dcla|num=3|since=c++11|constexpr=c++20|1=
 
tuple& operator=( tuple&& other ) noexcept(/* see below */);
 
tuple& operator=( tuple&& other ) noexcept(/* see below */);
|since2=c++20|dcl2=
 
constexpr tuple& operator=( tuple&& other ) noexcept(/* see below */);
 
 
}}
 
}}
 
{{dcl|num=4|since=c++23|1=
 
{{dcl|num=4|since=c++23|1=
 
constexpr const tuple& operator=( tuple&& other ) const;
 
constexpr const tuple& operator=( tuple&& other ) const;
 
}}
 
}}
{{dcl rev multi|num=5|since1=c++11|dcl1=
+
{{dcla|num=5|since=c++11|constexpr=c++20|1=
 
template< class... UTypes >
 
template< class... UTypes >
 
tuple& operator=( const tuple<UTypes...>& other );
 
tuple& operator=( const tuple<UTypes...>& other );
|since2=c++20|dcl2=
 
template< class... UTypes >
 
constexpr tuple& operator=( const tuple<UTypes...>& other );
 
 
}}
 
}}
 
{{dcl|num=6|since=c++23|1=
 
{{dcl|num=6|since=c++23|1=
Line 29: Line 22:
 
constexpr const tuple& operator=( const tuple<UTypes...>& other ) const;
 
constexpr const tuple& operator=( const tuple<UTypes...>& other ) const;
 
}}
 
}}
{{dcl rev multi|num=7|since1=c++11|dcl1=
+
{{dcla|num=7|since=c++11|constexpr=c++20|1=
 
template< class... UTypes >
 
template< class... UTypes >
 
tuple& operator=( tuple<UTypes...>&& other );
 
tuple& operator=( tuple<UTypes...>&& other );
|since2=c++20|dcl2=
 
template< class... UTypes >
 
constexpr tuple& operator=( tuple<UTypes...>&& other );
 
 
}}
 
}}
 
{{dcl|num=8|since=c++23|1=
 
{{dcl|num=8|since=c++23|1=
Line 40: Line 30:
 
constexpr const tuple& operator=( tuple<UTypes...>&& other ) const;
 
constexpr const tuple& operator=( tuple<UTypes...>&& other ) const;
 
}}
 
}}
{{dcl rev multi|num=9|since1=c++11|dcl1=
+
{{dcla|num=9|since=c++11|constexpr=c++20|1=
 
template< class E1, class E2 >
 
template< class E1, class E2 >
 
tuple& operator=( const std::pair<E1, E2>& p );
 
tuple& operator=( const std::pair<E1, E2>& p );
|since2=c++20|dcl2=
 
template< class E1, class E2 >
 
constexpr tuple& operator=( const std::pair<E1, E2>& p );
 
 
}}
 
}}
 
{{dcl|num=10|since=c++23|1=
 
{{dcl|num=10|since=c++23|1=
Line 51: Line 38:
 
constexpr const tuple& operator=( const std::pair<E1, E2>& p ) const;
 
constexpr const tuple& operator=( const std::pair<E1, E2>& p ) const;
 
}}
 
}}
{{dcl rev multi|num=11|since1=c++11|dcl1=
+
{{dcla|num=11|since=c++11|constexpr=c++20|1=
 
template< class E1, class E2 >
 
template< class E1, class E2 >
 
tuple& operator=( std::pair<E1, E2>&& p );
 
tuple& operator=( std::pair<E1, E2>&& p );
|since2=c++20|dcl2=
 
template< class E1, class E2 >
 
constexpr tuple& operator=( std::pair<E1, E2>&& p );
 
 
}}
 
}}
 
{{dcl|num=12|since=c++23|1=
 
{{dcl|num=12|since=c++23|1=

Latest revision as of 19:23, 13 May 2024

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
 
tuple& operator=( const tuple& other );
(1) (since C++11)
(constexpr since C++20)
constexpr const tuple& operator=( const tuple& other ) const;
(2) (since C++23)
tuple& operator=( tuple&& other ) noexcept(/* see below */);
(3) (since C++11)
(constexpr since C++20)
constexpr const tuple& operator=( tuple&& other ) const;
(4) (since C++23)
template< class... UTypes >
tuple& operator=( const tuple<UTypes...>& other );
(5) (since C++11)
(constexpr since C++20)
template< class... UTypes >
constexpr const tuple& operator=( const tuple<UTypes...>& other ) const;
(6) (since C++23)
template< class... UTypes >
tuple& operator=( tuple<UTypes...>&& other );
(7) (since C++11)
(constexpr since C++20)
template< class... UTypes >
constexpr const tuple& operator=( tuple<UTypes...>&& other ) const;
(8) (since C++23)
template< class E1, class E2 >
tuple& operator=( const std::pair<E1, E2>& p );
(9) (since C++11)
(constexpr since C++20)
template< class E1, class E2 >
constexpr const tuple& operator=( const std::pair<E1, E2>& p ) const;
(10) (since C++23)
template< class E1, class E2 >
tuple& operator=( std::pair<E1, E2>&& p );
(11) (since C++11)
(constexpr since C++20)
template< class E1, class E2 >
constexpr const tuple& operator=( std::pair<E1, E2>&& p ) const;
(12) (since C++23)
template< tuple-like UTuple >
constexpr tuple& operator=( UTuple&& u );
(13) (since C++23)
template< tuple-like UTuple >
constexpr const tuple& operator=( UTuple&& u ) const;
(14) (since C++23)

Replaces the contents of the tuple with the contents of another tuple-like object.

In the descriptions that follow, let

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

where indexing is zero-based.

1) Copy assignment operator. Assigns each element of other to the corresponding element of *this.
This overload is defined as deleted unless std::is_copy_assignable<Ti>::value is true for all Ti.
2) Copy assignment operator for const-qualified operand. Assigns each element of other to the corresponding element of *this.
This overload participates in overload resolution only if std::is_copy_assignable_v<const Ti> is true for all Ti.
3) Move assignment operator. For all i, assigns std::forward<Ti>(std::get<i>(other)) to std::get<i>(*this).
This overload participates in overload resolution only if std::is_move_assignable<Ti>::value is true for all Ti.
4) Move assignment operator for const-qualified operand. For all i, assigns std::forward<Ti>(std::get<i>(other)) to std::get<i>(*this).
This overload participates in overload resolution only if std::is_assignable_v<const Ti&, Ti> is true for all Ti.
5) For all i, assigns std::get<i>(other) to std::get<i>(*this).
This overload participates in overload resolution only if sizeof...(Types) == sizeof...(UTypes), and std::is_assignable<Ti&, const Ui&>::value is true for all corresponding pairs of types Ti and Ui.
6) For all i, assigns std::get<i>(other) to std::get<i>(*this).
This overload participates in overload resolution only if sizeof...(Types) == sizeof...(UTypes), and std::is_assignable_v<const Ti&, const Ui&> is true for all corresponding pairs of types Ti and Ui.
7) For all i, assigns std::forward<Ui>(std::get<i>(other)) to std::get<i>(*this).
This overload participates in overload resolution only if sizeof...(Types) == sizeof...(UTypes), and std::is_assignable<Ti&, Ui>::value is true for all corresponding pairs of types Tiand Ui.
8) For all i, assigns std::forward<Ui>(std::get<i>(other)) to std::get<i>(*this).
This overload participates in overload resolution only if sizeof...(Types) == sizeof...(UTypes), and std::is_assignable_v<const Ti&, Ui> is true for all corresponding pairs of types Ti and Ui.
9) Assigns p.first to the first element of *this and p.second to the second element of *this.
This overload participates in overload resolution only if
10) Assigns p.first to the first element and p.second to the second element.
This overload participates in overload resolution only if
11) Assigns std::forward<E1>(p.first) to the first element of *this and std::forward<E2>(p.second) to the second element of *this.
This overload participates in overload resolution only if
12) Assigns std::forward<E1>(p.first) to the first element and std::forward<E2>(p.second) to the second element.
This overload participates in overload resolution only if
13) For all i, assigns std::get<i>(std::forward<UTuple>(u)) to std::get<i>(*this).
This overload participates in overload resolution only if
14) For all i, assigns std::get<i>(std::forward<UTuple>(u)) to std::get<i>(*this).
This overload participates in overload resolution only if

Contents

[edit] Parameters

other - tuple to replace the contents of this tuple
p - pair to replace the contents of this 2-tuple
u - tuple-like object to replace the contents of this tuple

[edit] Return value

*this

[edit] Exceptions

1,2) May throw implementation-defined exceptionsif the assignment of one of the types in Types throws an exception.
3)
noexcept specification:  
noexcept(

    std::is_nothrow_move_assignable<T0>::value &&
    std::is_nothrow_move_assignable<T1>::value &&
    std::is_nothrow_move_assignable<T2>::value &&
    ...

)
4-14) May throw implementation-defined exceptionsif the assignment of one of the types in Types throws an exception.

[edit] Example

#include <iostream>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>
 
// helper function to print std::vector<int>
std::ostream& operator<<(std::ostream& os, std::vector<int> const& v)
{
    os << '{';
    for (std::size_t t = 0; t != v.size(); ++t)
        os << v[t] << (t + 1 < v.size() ? ", " : "");
    return os << '}';
}
 
// helpers to print a tuple of any size
template<class... Args>
void print_tuple(std::string_view name, const std::tuple<Args...>& t)
{
    std::cout << name << " = {";
    std::apply([&](auto&& arg, auto&&... args)
    {
        std::cout << arg;
        ((std::cout << ", " << args), ...);
    }, t);
    std::cout << '}';
}
 
template<class Tuple1, class Tuple2>
void print_tuples(std::string_view name1, const Tuple1& t1,
                  std::string_view name2, const Tuple2& t2)
{
    print_tuple(name1, t1);
    std::cout << ", ";
    print_tuple(name2, std::tuple(t2));
    std::cout << "\n\n";
}
 
int main()
{
    // Tuple to tuple examples //
    std::tuple<int, std::string, std::vector<int>>
        t1{1, "alpha", {1, 2, 3}},
        t2{2, "beta", {4, 5}};
    print_tuples("1) t1", t1, "t2", t2);
 
    // Normal copy assignment
    // operator=( const tuple& other );
    t1 = t2;
    print_tuples("2) t1 = t2;\n   t1", t1, "t2", t2);
 
    // Normal move assignment
    // operator=( tuple&& other );
    t1 = std::move(t2);
    print_tuples("3) t1 = std::move(t2);\n   t1", t1, "t2", t2);
 
    // Converting copy assignment
    // operator=( const tuple<UTypes...>& other );
    std::tuple<short, const char*, std::vector<int>> t3{3, "gamma", {6, 7, 8}};
    t1 = t3;
    print_tuples("4) t1 = t3;\n   t1", t1, "t3", t3);
 
    // Converting move assignment
    // operator=( tuple<UTypes...>&& other );
    t1 = std::move(t3);
    print_tuples("5) t1 = std::move(t3);\n   t1", t1, "t3", t3);
 
    // Pair to tuple examples //
    std::tuple<std::string, std::vector<int>> t4{"delta", {10, 11, 12}};
    std::pair<const char*, std::vector<int>> p1{"epsilon", {14, 15, 16}};
    print_tuples("6) t4", t4, "p1", p1);
 
    // Converting copy assignment from std::pair
    // operator=( const std::pair<U1, U2>& p );
    t4 = p1;
    print_tuples("7) t4 = p1;\n   t4", t4, "p1", p1);
 
    // Converting move assignment from std::pair
    // operator=( std::pair<U1, U2>&& p );
    t4 = std::move(p1);
    print_tuples("8) t4 = std::move(p1);\n   t4", t4, "p1", p1);
}

Possible output:

1) t1 = {1, alpha, {1, 2, 3}}, t2 = {2, beta, {4, 5}}
 
2) t1 = t2;
   t1 = {2, beta, {4, 5}}, t2 = {2, beta, {4, 5}}
 
3) t1 = std::move(t2);
   t1 = {2, beta, {4, 5}}, t2 = {2, , {}}
 
4) t1 = t3;
   t1 = {3, gamma, {6, 7, 8}}, t3 = {3, gamma, {6, 7, 8}}
 
5) t1 = std::move(t3);
   t1 = {3, gamma, {6, 7, 8}}, t3 = {3, gamma, {}}
 
6) t4 = {delta, {10, 11, 12}}, p1 = {epsilon, {14, 15, 16}}
 
7) t4 = p1;
   t4 = {epsilon, {14, 15, 16}}, p1 = {epsilon, {14, 15, 16}}
 
8) t4 = std::move(p1);
   t4 = {epsilon, {14, 15, 16}}, p1 = {epsilon, {}}

[edit] 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 2729 C++11 operator= was unconstrained and might
result in unnecessary undefined behavior
constrained

[edit] See also

constructs a new tuple
(public member function) [edit]
assigns the contents
(public member function of std::pair<T1,T2>) [edit]