2015-03-31 20 views
3

在C++ Con 2014的Herb Sutter's talk中,除了其他內容外,他還討論了按價值傳遞,引用等等。一種技術,他介紹了在這個雖然是人爲的例子是:在Herb Sutter's C++ Con 2014的演講中完美的代理人

using namespace std; 

class employee{ 
    string name_; 
public: 
    template<class String, class = enable_if_t<!is_same<decay_t<String>, string>::value>> 

    void set_name(String&& name) noexcept(is_nothrow_assignable<string&, String>::value){ 
     name_ = forward<String>(name); 
    } 
}; 

我明白String&&通用轉發引用作爲String被推斷的模板類型,因此,人們應該使用forward<String>(name)。雖然我對模板元編程有一些非常有限的經驗,但對於我來說,不知道什麼是不知名的臨時參數的目的,enable_if_t...,並且會解釋其解釋其目的。 noexcept如何工作?什麼會是錯的,如果一個曾經天真地寫着:因爲std::enable_if_t使用

template<class String> 
void set_name(String&& name){ 
    name_ = forward<String>(name); 
} 

回答

3

這是爲了確保set_name只能通過對std::string的l或r值引用來調用,以允許任何cv限定符。

它的工作原理採用SFINAE:如果decay結果荷蘭國際集團的String模板參數是不是std::stringenable_if_t將失敗的類型檢查,從而使模板將從候選集中刪除同一類型。

+0

請注意,如果您觀看視頻,「幻燈片」版本會將其顯示爲「!is_same」,如果您在說話時看着他的肩膀,它就是'is_same'。我懷疑他想要'is_same'版本。這大概在視頻的1:17:00左右。 – 2015-03-31 14:16:37

+0

是的,這就是我所設想的,否則代碼似乎很奇怪。 – TartanLlama 2015-03-31 14:17:54

+0

只需要說明decay_t部分的解釋:decay_t 是您在將字符串傳遞給函數時按值傳遞的類型。因此,enable_if(當更正爲刪除「!」時)使得set_name僅在與std :: string類型一起使用時才存在,因爲它通過值傳遞到函數中,但其行爲好像沒有隱式轉換到std :: string。這不是最好的例子,因爲我認爲大多數用戶都希望對任何可以分配給std :: string實例的類型使用set_name - 我並不是要批評它,但我希望能帶來一些觀點以此爲例。 – codeshot 2015-08-23 19:00:12

1

該不願透露姓名的模板參數是必需的。參數不需要(在模板函數中使用),所以它可以是未命名的。

std::enable_if_t作品使用SFINAE。如果std::enable_if_t的參數爲false,則不會爲該參數生成函數的代碼。

有關std::enable_if_t的更多信息,請參閱some documentation。您也可以看看Template Meta-Programming wikibook或SFINAE and enable_if文章。