250x250
Notice
Recent Posts
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
관리 메뉴

일상 코딩

[C++/CPP] 19.07. Perfect forwarding std::forward 본문

C++/따배C++ 19강 모던 C++ 기능들

[C++/CPP] 19.07. Perfect forwarding std::forward

polarcompass 2021. 12. 30. 04:17
728x90
#include<iostream>
#include<vector>
#include<utility> // std::forward

using namespace std;

struct MyStruct
{};

void func(MyStruct &s)
{
    cout << "Pass by L-ref" << endl;
}

void func(MyStruct &&s)
{
    cout << "Pass by R-ref" << endl;
}

// template<typename T>
// void func_wrapper(T t)
// {
//     func(t);
// }

template<typename T>
void func_wrapper(T &&t)
{
    // forward는 t가 L-value 이면, L-value 돌려주고
    // forward는 t가 R-value 이면, R-value 돌려준다.
    func(std::forward<T>(t));
}

int main()
{
    {
        // L, R 구분 가능
        MyStruct s;
        func(s); // L-value
        func(MyStruct()); // R-value
    }

    {
        // L,R 구분 안됨.
        // L 만됨.
        MyStruct s;
        func_wrapper(s);
        func_wrapper(MyStruct());
    }

    return 0;
}
#include<iostream>
#include<vector>
#include<cstdio>
#include<utility> // std::forward

using namespace std;

class CustomVector
{
public:
    unsigned n_data = 0;
    int *ptr = nullptr;

    CustomVector(const unsigned &_n_data, const int &_init = 0)
    {
        cout << "Constructor" << endl;
        init( _n_data, _init);
    }

    CustomVector(CustomVector &L_input)
    {
        cout << "Copy constructor" << endl;

        init(L_input.n_data);

        for (unsigned i = 0; i < n_data; ++i)
            ptr[i] = L_input.ptr[i];
    }

    CustomVector(CustomVector &&R_input)
    {
        cout << "Move constructor" << endl;

        // 값을 넘겨주고(이동)
        n_data = R_input.n_data;
        ptr = R_input.ptr;

        // 다시 초기화
        R_input.n_data = 0;
        R_input.ptr = nullptr;
    }

    ~CustomVector()
    {
        delete[] ptr;
    }

    void init(const unsigned &_n_data, const int &_init = 0 )
    {
        n_data = _n_data;
        ptr = new int[n_data];
        for (unsigned i = 0; i < n_data; ++i)
            ptr[i] = _init;
    }
};

void doSomething(CustomVector &vec)
{
    cout << "Pass by L-reference" << endl;
    // copy constructor 호출
    CustomVector new_vec(vec);
}

void doSomething(CustomVector &&vec)
{
    cout << "Pass by R-reference" << endl;
    // move constructor 호출
    CustomVector new_vec(std::move(vec)); 
    // Note: vec itself is L-value
}

// L,R 구분되는 코드
template<typename T>
void doSomethingTemplate(T &&vec)
{
    doSomething(std::forward<T>(vec));
}

// L, R 구분하지 못하는 코드
// template<typename T>
// void doSomethingTemplate(T vec)
// {
//     doSomething(vec);
// }

int main()
{
        
        {
            CustomVector my_vec(10, 1024);

            // my_vec을 R-value 취급함
            CustomVector temp(std::move(my_vec));

            // my_vec에 있는 내용을 전부 이동시키고,
            // my_vec을 비워버림.
            cout << my_vec.n_data << endl;
        }

        {
            cout << endl;
            cout << "<Move Example>" << endl;
            CustomVector my_vec(10, 1024);
            cout << endl;

            doSomething(my_vec);
            cout << endl;
            doSomething(CustomVector(10,8));
        }

        {
            cout << endl;
            cout << "<Template Forward Example>" << endl;
            CustomVector my_vec(10, 1024);
            cout << endl;
            
            doSomethingTemplate(my_vec);
            cout << endl;
            doSomethingTemplate(CustomVector(10,8));
        }

        return 0;
}
728x90