2017年4月7日 星期五

C++ 副程式的 const左右值引用 的完美轉發

C++ 副程式的 const左右值引用 的完美轉發

tags: C++ Concept2

四種不同屬性的函式

已知存在著四種屬性
  • lvalue
  • lvalue const
  • rvalue
  • rvalue const
他們分別呼叫的副程式參數長這個樣子
void fun(int & i){
    cout << "fun L" << endl;
}
void fun(int const & i){
    cout << "fun L const" << endl;
}
void fun(int && i){
    cout << "fun R" << endl;
}
void fun(int const && i){
    cout << "fun R const" << endl;
}
如此宣告我們可以統一使用 fun() 這個名稱呼叫四種不同的函式,分別是這樣呼叫
    int a=0;
    int const b=0;

    fun(a);
    fun(b);
    fun(move(a));
    fun(move(b));

函式轉發

如果你想要用另一個副程式來呼叫這個 fun() 藉此組合更多的功能可能會遇到一些問題
  • const 與非 const
  • 右值進來有了名字變成左值

const 與非 const

可以試著重載const藉此可以同時引入兩種版本
template<class T>
void tran(T const & t){
    fun(t);
}
不過如此一來將導致你沒有辦法修改內容,可以透過加載右值參數達到正確的結果
template<class T>
void tran(T && t){
    fun(t);
}

消除名字

不過仍然有一個問題,它存在著名字會呼叫左值參數的函式,可以透過 forward<T>(t) 消除名字
template<class T>
void tran(T && t){
    fun(forward<T>(t));
}
如此一來我們就可以好像換了一個別名似的,用第二個名字自由的操作,可以在函式內加上一些功能,增加代碼的重複性。
template<class T>
void tran(T && t){
    // 其他功能
    fun(forward<T>(t));
}

fun();
tran();
需要 fun() 時使用他,需要fun() 加上一額外的功能使用 tran() ,並可將重複的代寫在一起

為什麼不是使用 move() 語意即可?

確實可以透過move()協助我們呼叫右值參數的函式,但是這也導致tan()只能呼叫右值,沒有呼叫左值的選擇權,除非你加載第二個tran()函式,但這樣結果並不好代碼要重寫兩次。

參考代碼

/*****************************************************************
Name : 
Date : 2017/04/07
By   : CharlotteHonG
Final: 2017/04/07
*****************************************************************/
#include <iostream>
using namespace std;

void fun(int & i){
    cout << "fun L" << endl;
}
void fun(int const & i){
    cout << "fun L const" << endl;
}
void fun(int && i){
    cout << "fun R" << endl;
}
void fun(int const && i){
    cout << "fun R const" << endl;
}

template<class T>
void tran(T && t){
    fun(forward<T>(t));
}
// && 解決了 const 與 non-constt 的問題
// forward 解決了引入的右值有了名字變成左值的問題
/*==============================================================*/
int main(int argc, char const *argv[]){
    int a=0;
    int const b=0;
    // fun(a);
    // fun(b);
    // fun(move(a));
    // fun(move(b));

    tran(a);
    tran(b);
    tran(move(a));
    tran(move(b));
    return 0;
}
/*==============================================================*/

沒有留言:

張貼留言