讓我們考慮一個簡單的類右值引用和構造函數參數
template< typename T >
class Wrapper {
public:
// Constructors?
private:
T wrapped;
};
它應該使用什麼樣的構造是有效的?
C++之前0X會有一個構造函數之一:
- const引用(
T const&
) - 如果類型是T
「重」, - 或值(
T
) - 如果類型T
是「輕」。
確定類型T
是「重」還是「輕」並不容易。
人們可以假設只有內建類型(int/floats/...)是「輕」。但這並不完全正確,因爲我們自己的Wrapper<int>
最有可能也應該被視爲「輕」類型。
像boost::call_traits
這樣的庫提供了一些手段,通過允許類型創建者將類型標記爲「輕」(通過提供適當的call_traits
專業化)來克服此困難。否則它將被視爲「重」。似乎可以接受。
但是,C++ 0x使情況變得更糟。因爲現在你也有參考(T&&
),它允許有效地採取(一些)「重」的對象。
因爲這個現在你必須之中選擇和:
- 只是const引用(
T const&
) - 如果類型T
是「重」,不支持移動語義(因爲無論有沒有 - 像大莢 - 或沒有寫,你有沒有影響), - 兩個const引用(
T const&
)和右值引用(T&&
) - 如果類型T
是「重」,不支持移動語義, - 只值(
T
) - 如果T
類型是「輕量級」或者是「重量級」但支持移動語義(即使進行了複製,也不會打擾使用,否則我們不得不自己複製T const&
...)。
還不容易分辨哪些類型是「重」,哪些類型是「輕」(如以前)。但是現在你也不知道類型T
是否支持移動語義(或者你是否?)。
一旦你換一個以上的值,因爲可能的構造函數重載數量呈指數級增長,這變得更加惱人。
有沒有解決這個問題的方法?
我雖然關於轉發(完美轉發)參數的一些模板構造函數,但我不確定是否會按需要工作。而且它還允許提供將被轉發給T
構造函數的不同類型的值。這可能被認爲是一個功能,但不一定。
您也可以使用具有相同完美轉發的可變參數構造函數來構造'value'。您只需編寫一個通用構造函數:'template Wrapper(U && ... us):value(std :: forward (us)...){} –
2012-07-20 11:29:43
@AlexandreC:是是的,已經在那:-) – 2012-07-20 11:30:02
只有一個問題:'std :: enable_if'在這裏並不是必須的(它不會改善錯誤報告)。這裏有什麼用處? – 2012-07-20 11:32:36