Namespaces
Variants

std::tuple<Types...>:: operator=

From ko.cppreference.net
< cpp β€Ž | utility β€Ž | tuple
Utilities library
tuple & operator = ( const tuple & other ) ;
(1) (C++11λΆ€ν„°)
(C++20λΆ€ν„° constexpr)
constexpr const tuple & operator = ( const tuple & other ) const ;
(2) (C++23λΆ€ν„°)
tuple & operator = ( tuple && other ) noexcept ( /* see below */ ) ;
(3) (C++11λΆ€ν„°)
(C++20λΆ€ν„° constexpr)
constexpr const tuple & operator = ( tuple && other ) const ;
(4) (C++23 이후)
template < class ... UTypes >
tuple & operator = ( const tuple < UTypes... > & other ) ;
(5) (C++11 이후)
(C++20 이후 constexpr)
template < class ... UTypes >
constexpr const tuple & operator = ( const tuple < UTypes... > & other ) const ;
(6) (C++23λΆ€ν„°)
template < class ... UTypes >
tuple & operator = ( tuple < UTypes... > && other ) ;
(7) (C++11λΆ€ν„°)
(C++20λΆ€ν„° constexpr)
template < class ... UTypes >
constexpr const tuple & operator = ( tuple < UTypes... > && other ) const ;
(8) (C++23 이후)
template < class E1, class E2 >
tuple & operator = ( const std:: pair < E1, E2 > & p ) ;
(9) (C++11λΆ€ν„°)
(C++20λΆ€ν„° constexpr)
template < class E1, class E2 >
constexpr const tuple & operator = ( const std:: pair < E1, E2 > & p ) const ;
(10) (C++23 이후)
template < class E1, class E2 >
tuple & operator = ( std:: pair < E1, E2 > && p ) ;
(11) (C++11 이후)
(C++20 이후 constexpr)
template < class E1, class E2 >
constexpr const tuple & operator = ( std:: pair < E1, E2 > && p ) const ;
(12) (C++23 이후)
template < tuple - like UTuple >
constexpr tuple & operator = ( UTuple && u ) ;
(13) (C++23 이후)
template < tuple - like UTuple >
constexpr const tuple & operator = ( UTuple && u ) const ;
(14) (C++23λΆ€ν„°)

νŠœν”Œμ˜ λ‚΄μš©μ„ λ‹€λ₯Έ νŠœν”Œκ³Ό μœ μ‚¬ν•œ 객체의 λ‚΄μš©μœΌλ‘œ λŒ€μ²΄ν•©λ‹ˆλ‹€.

λ‹€μŒ μ„€λͺ…μ—μ„œ λ‹€μŒκ³Ό 같이 κ°€μ •ν•©λ‹ˆλ‹€.

  • i κ°€ λ²”μœ„ [ ​ 0 ​ , sizeof... ( Types ) ) λ‚΄μ—μ„œ μˆœμ„œλŒ€λ‘œ μ‘΄μž¬ν•˜κ³ ,
  • Ti κ°€ 클래슀 ν…œν”Œλ¦Ώ λ§€κ°œλ³€μˆ˜ 팩 Types 의 i 번째 νƒ€μž…μ΄λ©°,
  • Ui κ°€ UTypes λΌλŠ” μ΄λ¦„μ˜ ν•¨μˆ˜ ν…œν”Œλ¦Ώ λ§€κ°œλ³€μˆ˜ νŒ©μ—μ„œ i 번째 νƒ€μž…μΈ 경우,

인덱싱은 0λΆ€ν„° μ‹œμž‘ν•©λ‹ˆλ‹€.

1) 볡사 ν• λ‹Ή μ—°μ‚°μž. other 의 각 μš”μ†Œλ₯Ό * this 의 ν•΄λ‹Ή μš”μ†Œμ— ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λͺ¨λ“  Ti 에 λŒ€ν•΄ std:: is_copy_assignable < Ti > :: value κ°€ true 인 경우λ₯Ό μ œμ™Έν•˜κ³  μ‚­μ œλœ κ²ƒμœΌλ‘œ μ •μ˜λ©λ‹ˆλ‹€.
2) const둜 ν•œμ •λœ ν”Όμ—°μ‚°μžμ— λŒ€ν•œ 볡사 ν• λ‹Ή μ—°μ‚°μž. other 의 각 μš”μ†Œλ₯Ό * this 의 ν•΄λ‹Ή μš”μ†Œμ— ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λͺ¨λ“  Ti 에 λŒ€ν•΄ std:: is_copy_assignable_v < const Ti > κ°€ true 인 κ²½μš°μ—λ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€.
3) 이동 ν• λ‹Ή μ—°μ‚°μž. λͺ¨λ“  i 에 λŒ€ν•΄, std:: forward < Ti > ( std :: get < i > ( other ) ) λ₯Ό std :: get < i > ( * this ) 에 ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λͺ¨λ“  Ti 에 λŒ€ν•΄ std:: is_move_assignable < Ti > :: value κ°€ true 인 κ²½μš°μ—λ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€.
4) const ν•œμ • ν”Όμ—°μ‚°μžμ— λŒ€ν•œ 이동 ν• λ‹Ή μ—°μ‚°μž. λͺ¨λ“  i 에 λŒ€ν•΄, std:: forward < Ti > ( std :: get < i > ( other ) ) λ₯Ό std :: get < i > ( * this ) 에 ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λͺ¨λ“  Ti 에 λŒ€ν•΄ std:: is_assignable_v < const Ti & , Ti > κ°€ true 인 κ²½μš°μ—λ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€.
5) λͺ¨λ“  i 에 λŒ€ν•΄, std :: get < i > ( other ) λ₯Ό std :: get < i > ( * this ) 에 ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λ‹€μŒ μ‘°κ±΄μ—μ„œλ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€: sizeof... ( Types ) == sizeof... ( UTypes ) 이고, std:: is_assignable < Ti & , const Ui & > :: value κ°€ λͺ¨λ“  ν•΄λ‹Ή νƒ€μž… 쌍 Ti 와 Ui 에 λŒ€ν•΄ true 인 κ²½μš°μž…λ‹ˆλ‹€.
6) λͺ¨λ“  i 에 λŒ€ν•΄, std :: get < i > ( other ) λ₯Ό std :: get < i > ( * this ) 에 ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λ‹€μŒ 쑰건이 좩쑱될 λ•Œλ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€: sizeof... ( Types ) == sizeof... ( UTypes ) , 그리고 λͺ¨λ“  ν•΄λ‹Ή νƒ€μž… 쌍 Ti 와 Ui 에 λŒ€ν•΄ std:: is_assignable_v < const Ti & , const Ui & > κ°€ true 인 경우.
7) λͺ¨λ“  i 에 λŒ€ν•΄, std:: forward < Ui > ( std :: get < i > ( other ) ) λ₯Ό std :: get < i > ( * this ) 에 ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λ‹€μŒ μ‘°κ±΄μ—μ„œλ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€: sizeof... ( Types ) == sizeof... ( UTypes ) , 그리고 λͺ¨λ“  ν•΄λ‹Ή νƒ€μž… 쌍 Ti 와 Ui 에 λŒ€ν•΄ std:: is_assignable < Ti & , Ui > :: value κ°€ true 인 경우.
8) λͺ¨λ“  i 에 λŒ€ν•΄, std:: forward < Ui > ( std :: get < i > ( other ) ) λ₯Ό std :: get < i > ( * this ) 에 ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λ‹€μŒ μ‘°κ±΄μ—μ„œλ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€: sizeof... ( Types ) == sizeof... ( UTypes ) , 그리고 λͺ¨λ“  ν•΄λ‹Ή νƒ€μž… 쌍 Ti 와 Ui 에 λŒ€ν•΄ std:: is_assignable_v < const Ti & , Ui > κ°€ true 인 경우.
9) p. first λ₯Ό * this 의 첫 번째 μš”μ†Œμ— ν• λ‹Ήν•˜κ³ , p. second λ₯Ό * this 의 두 번째 μš”μ†Œμ— ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λ‹€μŒ μ‘°κ±΄μ—μ„œλ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€:
10) p. first 에 첫 번째 μš”μ†Œλ₯Ό ν• λ‹Ήν•˜κ³  p. second 에 두 번째 μš”μ†Œλ₯Ό ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λ‹€μŒ 쑰건이 λͺ¨λ‘ 좩쑱될 λ•Œλ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€:
11) std:: forward < E1 > ( p. first ) λ₯Ό * this 의 첫 번째 μš”μ†Œμ— ν• λ‹Ήν•˜κ³ , std:: forward < E2 > ( p. second ) λ₯Ό * this 의 두 번째 μš”μ†Œμ— ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λ‹€μŒ 쑰건을 λͺ¨λ‘ λ§Œμ‘±ν•  λ•Œλ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€:
12) 첫 번째 μš”μ†Œμ— std:: forward < E1 > ( p. first ) λ₯Ό ν• λ‹Ήν•˜κ³ , 두 번째 μš”μ†Œμ— std:: forward < E2 > ( p. second ) λ₯Ό ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λ‹€μŒ 쑰건을 λͺ¨λ‘ λ§Œμ‘±ν•  λ•Œλ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€:
13) λͺ¨λ“  i 에 λŒ€ν•΄, std :: get < i > ( std:: forward < UTuple > ( u ) ) λ₯Ό std :: get < i > ( * this ) 에 ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λ‹€μŒ 쑰건을 λͺ¨λ‘ λ§Œμ‘±ν•  λ•Œλ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€:
14) λͺ¨λ“  i 에 λŒ€ν•΄, std :: get < i > ( std:: forward < UTuple > ( u ) ) λ₯Ό std :: get < i > ( * this ) 에 ν• λ‹Ήν•©λ‹ˆλ‹€.
이 μ˜€λ²„λ‘œλ“œλŠ” λ‹€μŒ 쑰건을 λͺ¨λ‘ λ§Œμ‘±ν•  λ•Œλ§Œ μ˜€λ²„λ‘œλ“œ 해결에 μ°Έμ—¬ν•©λ‹ˆλ‹€:

λͺ©μ°¨

λ§€κ°œλ³€μˆ˜

other - 이 νŠœν”Œμ˜ λ‚΄μš©μ„ λŒ€μ²΄ν•  νŠœν”Œ
p - 이 2-νŠœν”Œμ˜ λ‚΄μš©μ„ λŒ€μ²΄ν•  νŽ˜μ–΄
u - tuple-like 이 νŠœν”Œμ˜ λ‚΄μš©μ„ λŒ€μ²΄ν•  νŠœν”Œ-라이크 객체

λ°˜ν™˜κ°’

* this

μ˜ˆμ™Έ

1,2) Types 에 ν¬ν•¨λœ νƒ€μž…λ“€ 쀑 ν•˜λ‚˜μ˜ 할당이 μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λŠ” 경우, κ΅¬ν˜„μ—μ„œ μ •μ˜λœ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.
3)
noexcept λͺ…μ„Έ:
noexcept (

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

)
4-14) Types 에 ν¬ν•¨λœ νƒ€μž… 쀑 ν•˜λ‚˜μ˜ 할당이 μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λŠ” 경우, κ΅¬ν˜„μ—μ„œ μ •μ˜λœ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

예제

#include <iostream>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>
// 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 << '}';
}
// μž„μ˜ 크기의 νŠœν”Œμ„ 좜λ ₯ν•˜λŠ” 헬퍼 ν•¨μˆ˜
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()
{
    // νŠœν”Œμ—μ„œ νŠœν”Œλ‘œμ˜ λ³€ν™˜ 예제 //
    std::tuple<int, std::string, std::vector<int>>
        t1{1, "μ•ŒνŒŒ", {1, 2, 3}},
        t2{2, "베타", {4, 5}};
    print_tuples("1) t1", t1, "t2", t2);
    // 일반 볡사 ν• λ‹Ή
    // 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);
    // 볡사 ν• λ‹Ή λ³€ν™˜
    // operator=( const tuple<UTypes...>& other );
    std::tuple<short, const char*, std::vector<int>> t3{3, "감마", {6, 7, 8}};
    t1 = t3;
    print_tuples("4) t1 = t3;\n   t1", t1, "t3", t3);
    // 이동 ν• λ‹Ή λ³€ν™˜
    // operator=( tuple&& other );
    t1 = std::move(t3);
    print_tuples("5) t1 = std::move(t3);\n   t1", t1, "t3", t3);
    // Pair to tuple 예제 //
    std::tuple<std::string, std::vector<int>> t4{"델타", {10, 11, 12}};
    std::pair<const char*, std::vector<int>> p1{"μ—‘μ‹€λ‘ ", {14, 15, 16}};
    print_tuples("6) t4", t4, "p1", p1);
    // std::pairμ—μ„œ 볡사 ν• λ‹Ή λ³€ν™˜
    // operator=( const std::pair<U1, U2>& p );
    t4 = p1;
    print_tuples("7) t4 = p1;\n   t4", t4, "p1", p1);
    // std::pairμ—μ„œ 이동 ν• λ‹Ή λ³€ν™˜
    // operator=( std::pair<U1, U2>&& p );
    t4 = std::move(p1);
    print_tuples("8) t4 = std::move(p1);\n   t4", t4, "p1", p1);
}

κ°€λŠ₯ν•œ 좜λ ₯:

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, {}}

결함 λ³΄κ³ μ„œ

λ‹€μŒμ˜ λ™μž‘ λ³€κ²½ 결함 λ³΄κ³ μ„œλ“€μ€ 이전에 λ°œν‘œλœ C++ ν‘œμ€€μ— μ†ŒκΈ‰ μ μš©λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

DR 적용 λŒ€μƒ κ²Œμ‹œλœ λ™μž‘ μ˜¬λ°”λ₯Έ λ™μž‘
LWG 2729 C++11 operator = μ œμ•½ 쑰건이 μ—†μ–΄ λΆˆν•„μš”ν•œ
λ―Έμ •μ˜ λ™μž‘μ΄ λ°œμƒν•  수 μžˆμ—ˆμŒ
μ œμ•½ 쑰건 좔가됨

μ°Έκ³  ν•­λͺ©

μƒˆλ‘œμš΄ tuple 을 μƒμ„±ν•©λ‹ˆλ‹€
(public member function)
λ‚΄μš©μ„ ν• λ‹Ήν•©λ‹ˆλ‹€
( std::pair<T1,T2> 의 public member function)