2014-07-20 64 views
0

所以我有一個名爲std::map< std::string, boost::any >OptionsMap我想創建一個函數,它在地圖上的任何類型的(因此模板),並將其存儲。 下一個代碼是否工作?模板和右值使用引用作爲參數

template <typename T> 
void Set(std::string optionName, T&& optionValue) 
{ 
    OptionsMap[optionName] = optionValue; 
} 
+0

你有理由相信它不起作用嗎? –

+3

如果您打算進行完美的轉發,您錯過了對「std :: forward」的調用。 – chris

+0

@KerrekSB我還在學習rvalues等,所以我只是想確保 – ReBirTH

回答

3

通常,當函數模板接受通用引用(即推導類型的右值引用)時,應該使用forward來強制轉換函數參數,以便獲得與參數提供的值相同的值類別在函數調用:

template <typename T> 
void Set(std::string optionName, T&& optionValue) 
{ 
    OptionsMap[optionName] = std::forward<T>(optionValue); 
    //      ^^^^^^^^^^^^^^^ 
} 

參數變量optionValue本身始終是一個左值,所以不投,你會做什麼應該是移動的副本。如果類型是可複製的,則效率會低於預期;如果該類型不可複製(例如unique_ptr),那就更糟糕了:您的函數現在接受一個隨後無法編譯的參數。

+0

謝謝!如果我理解正確,前向函數從左值返回一個右值? – ReBirTH

+2

@ user3027108:不會。這將是'std :: move'。相比之下,'std :: forward'必須被賦予一個明確的模板參數,並且它恢復原始參數的正確的廣義值類別。 (例如見[這個答案](http://stackoverflow.com/a/3582313/596781)。) –

+0

參數'optionName'不應該是一個左值引用,所以它不會創建一個'std :: string'副本? – ReBirTH

1

當然。爲什麼它不工作?

boost::any::operator=接受任何數據類型的參數,滿足ValueType

我只是把價值和移動它,爲了前向兼容性,當boost::any開始支持移動語義。

template <typename T> 
void Set(std::string optionName, T optionValue) 
{ 
    OptionsMap[optionName] = std::move(optionValue); 
} 

傳遞右值這個功能時,它的移動將移動它。這由標準保證。

+0

是的,但它是最有效率/正確的方式嗎? – ReBirTH

+0

@ user3027108如果不是,我爲什麼會建議呢? – rightfold

+0

@rightfold OP提到'T'爲'T &&'(通用參考)。你寫它作爲一個價值傳遞強制執行副本 –

相關問題