2016-06-10 48 views
3

我有很多代碼以某種方式執行完全相同的操作(繼承代碼),並且我希望在重寫它時壓縮代碼而不會丟失功能。例如,讓我們來看看下面的功能:如何在C++中省略不同參數的複製函數定義

fnc(largetype & a, largetype & b) { f(A); f(B); }; 
fnc(largetype && a, largetype & b) { f(A); f(B); }; 
fnc(largetype & a, largetype && b) { f(A); f(B); }; 
fnc(largetype && a, largetype && b) { f(A); f(B); }; 

所有這些都在做同樣的事情,但參數可以是右值或左值不破壞功能邏輯。我想讓用戶通過任何適合的問題,但我也不想複製粘貼所有代碼。我可以這樣做:

fnc(largetype & a, largetype & b) { f(A); f(B); }; 
fnc(largetype && a, largetype & b) { fnc(a,b) }; 
fnc(largetype & a, largetype && b) { fnc(a,b) }; 
fnc(largetype && a, largetype && b) { fnc(a,b) }; 

這在技術上是正確的,特別是在內聯中,但對我來說似乎是錯誤的。有沒有其他更好的方法來實現這樣的效果?

唯一的要求是作爲參數傳遞的類型可能/會比默認的內存塊大小大,所以避免複製是至關重要的。另外,參數可以更小但也可以是右值的非零機會。線程安全是可選的。

我認爲模板這些功能,但這在我看來也是某種錯誤的方法。模板用不同的可接受類型解決問題。在我的情況下,類型是相同的,只是以不同的方式傳遞。

+6

使用[完美轉發]模板函數(http://stackoverflow.com/questions/3582001/advantages-of-using-forward)。 –

+0

其實完美... – Esavier

回答

5

作爲@SamVarshavchik評論說,這是一個完美的轉發通常的候選人。一種簡單的方法:

template<typename T, typename U> 
void fnc(T&& a, U&& b) 
{ 
    f(std::forward<T>(a)); 
    f(std::forward<U>(b)); 
} 

如果用戶通過在不largetype類型的對象,錯誤網站將在此函數,這可能會造成混淆給用戶。推錯誤站點調用者的代碼,我們可以使用SFINAE來約束的參數類型:

template< 
    typename T, typename U, 
    typename = std::enable_if_t< 
     std::is_same<std::decay_t<T>, largetype>{} 
    && std::is_same<std::decay_t<U>, largetype>{} 
    > 
> 
void fnc(T&& a, U&& b) 
{ 
    f(std::forward<T>(a)); 
    f(std::forward<U>(b)); 
} 

Online Demo

或者,你可能想保留錯誤網站fnc內部,而是給出一個更清晰的錯誤信息 - 這可以用static_assert來完成:

template<typename T, typename U> 
void fnc(T&& a, U&& b) 
{ 
    static_assert(std::is_same<std::decay_t<T>, largetype>{}, 
        "argument 'a' must be of type 'largetype'"); 
    static_assert(std::is_same<std::decay_t<U>, largetype>{}, 
        "argument 'b' must be of type 'largetype'"); 

    f(std::forward<T>(a)); 
    f(std::forward<U>(b)); 
} 

Online Demo

相關問題