2016-09-16 93 views
4

在下面的代碼中,使用&&有什麼好處? 該代碼是從答案在Specialize same operator for different traits這段代碼中&&的優點是什麼?

this問題,我得到一個&&參數意味着它是一個可以由該函數修改的參考。

decay_t可能阻止編譯器解釋的變量作爲數組的引用,如在What is std::decay and when it should be used?

std::forward是如所描述的here完美轉發。爲什麼我們需要這個轉發?

謝謝。

#include <iostream> 
#include <type_traits> 
#include<utility> 

class A; 

template <typename T> 
struct is_A : std::false_type {}; 
template <> struct is_A<A> : std::true_type {}; 

template <typename T> 
struct is_int : std::false_type {}; 
template <> struct is_int<int> : std::true_type {}; 
template <> struct is_int<long> : std::true_type {}; 

class A{ 
public: 
    int val; 

    void print(void){ 
     std::cout << val << std::endl; 
    } 

    template <typename T1> 
    std::enable_if_t<is_int<std::decay_t<T1>>::value, void> 
    operator=(T1 && input){ 
     val = 2*std::forward<T1>(input); 
    } 

    template <typename T1> 
    std::enable_if_t<is_A<std::decay_t<T1>>::value,void> 
    operator=(T1 && Bb){ 
     val = 5*std::forward<T1>(Bb).val; 
    } 
}; 

int main(void){ 
    A Aa; 
    A Bb; 
    int in_a = 3; 
    Aa = in_a; 
    Bb = Aa; 
    Aa.print(); //This should give 6. (3x2) 
    Bb.print(); //This should give 30. (6x5) 
} 
+2

此代碼中的'&&'半正式地稱爲轉發引用。它們綁定到左值和右值,並且傳遞給'std :: forward'的'T1'包含關於對象最初是左值還是右值的信息。總之,'&&'的「優勢」在於它可以完美轉發。 – KABoissonneault

+1

所以整個事情就是讓完美的轉發......這是否也避免創建任何'T1 && Bb'參數的任何部分的臨時副本? – rxu

+1

@rxu:它不會創建一個副本,除非它被轉發的函數(或運算符重載)通過值接收參數(或通過轉發引用,然後它本身以傳值方式使用它)。 – ShadowRanger

回答

2

其實,這是一個(讓我說)這樣的例子代碼工作。
事實上,標準說:

用戶聲明的拷貝賦值運算符X ::運算符=是類X的非靜態非模板成員函數X型的只有一個參數,X &,const X &,易失性X &或const volatileX &。

此外:

如果類定義不明確聲明拷貝賦值運算符,一個是隱式聲明。

現在,嘗試複製分配一個常量引用變量,作爲一個例子:

Bb = static_cast<const A&>(Aa); 

其結果將是不再是一個預期。

無論如何,只要您只處理非cv限定的左值/右值引用,答案中使用的轉發引用就能正常工作,如示例代碼所示。
攔截一堆特定類型,並完成其工作。就這樣。

正如@ Jarod42在評論中提到:

注意,你還是得寫operator=(const A&)來處理它,因爲它是特殊的。

的確不那麼特別。如果您沒有定義它,那麼在該代碼中沒有適當的複製賦值運算符。
正如所說的意見,以確定它

[...]就留給讀者做練習。 :-)

那麼,這樣做的優勢是什麼?
提供最小的工作解決方案的捷徑。當然,這不是一個完整的,生產就緒的代碼。