2014-03-04 74 views
17

它實際上是關於界面設計一個一般性的問題,但對我來說,只是採取std::pair作爲一個例子很簡單:的std ::對構造接口

template <class T1, class T2> 
struct pair { 
    ... 
    pair(const T1& x, const T2& y); 
    template<class U, class V> pair(U&& x, V&& y); 
    ... 
}; 

因此,我們可以看到有兩個重載都採取2參數來初始化這兩個成員。我的問題是,提供第一個的好處是什麼,而第二個是可用的?是否有任何類型的參數只能傳遞給第一個而不是第二個?

(就讓我們拋開標準庫的考慮向後兼容性的同時,並討論了接口設計作爲一個一般性的問題。)

+1

有可能對某些類型的可移動的,但不可複製。另一方面,某些類型也可以是可複製的,但不可移動。這兩個構造函數允許'pair'與這兩種類型一起使用。 – Cornstalks

+5

@Cornstalks第二個構造函數可以處理這兩種情況,它使用通用引用。見http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers – DanielKO

+0

看看[這個簡短的例子](http://ideone.com/D1iHwn),它顯示在所有常見情況下調用第二個變體。不過,我相信在極少數情況下,調用第二次重載是不可能的。但這是一個有趣的問題。 – Excelcius

回答

11

樣品實施

template<typename T1, typename T2> 
struct simple_pair { 
    simple_pair (T1 const& v1, T2 const& v2) // (1) 
    : first (v1) 
    , second (v2) 
    { } 

    template<class U, class V>  
    simple_pair (U&& v1, V&& v2)    // (2) 
    : first (std::forward<U> (v1)) 
    , second (std::forward<V> (v2)) 
    { } 

    T1 first; 
    T2 second; 
}; 

即使盡管提供過載(1)(2)似乎是多餘的,但有些情況下第二個不可用,並且第一個不僅是首選,而且是第實際上需要。

考慮到我們想在構造函數simple_pair的構造函數中構造一些或兩個值,而沒有第一個重載,我們將不得不第二次指定至少一個類型。

T val; 

simple_pair<T, U> p1 { {}, {} }; // only (1) is applicable 
simple_pair<T, U> p2 { val, {} }; // only (1) is applicable 
simple_pair<T, U> p3 { T {}, U {} }; // can use (1) and (2), but this require a lot of typing 

替代實現

如果我們不是有使用的東西的下面,我們可以繞過「多餘」重載,因爲編譯器會後來才知道我們」是什麼類型的實行d喜歡在需要這些信息的情況下構建。

template<typename T1, typename T2> 
struct simple_pair { 
    template<class U = T1, class V = T2>  
    simple_pair (U&& v1, V&& v2)    
    : first (std::forward<U> (v1)) 
    , second (std::forward<V> (v2)) 
    { } 

    T1 first; 
    T2 second; 
}; 

T val; 

    simple_pair<T, U> p1 { {}, {} }; // legal 
    simple_pair<T, U> p2 { val, {} }; // legal 
    simple_pair<T, U> p3 { T {}, U {} }; // legal 

爲什麼不std::pair陳述使用可替代實現方式來實現?

我們只能猜測,但可能是因爲向後兼容性和指定它現在的方式使庫實現者的實現變得容易。

通過具有兩個獨立的過載一個可以很容易地通過使用宏(查看是否我們使用c++11(或更高版本))有條件地將它,而不是選擇加入有條件出來,然後再添加其他禁用template<class U, class V> simple_pair (U&&, V&&)過載。


進一步潛在原因

  • 從標準中刪除的東西總是做一個微妙的東西..繼比抱歉成語更好的安全; 「如果它不傷害,將它留在。」 - @PlasmaHH

  • 每個人都知道的代碼越行你寫,更好的程序員,你是...和更好的程序員,你是;你得到的報酬越多。


1.肯定得不多,但心裏很不舒服..它不會傷害是一個有點迂腐.. ;-)

+2

好的,趕上!這是一個有效的案例。謝謝! – goodbyeera

+0

一些無關緊要的想法:這是否意味着使用'T {}'作爲初始值設定項而不是'{}'更好,因爲它可以在此情況下啓用移動構建? (雖然複製和移動構造在值初始化對象(可能只包含非常少的數據)的性能方面沒有太大差異。 – goodbyeera