2015-05-06 38 views
1

我正在嘗試使用variadic模板編寫sum函數。 在代碼中,我會寫類似從字符數組類型演繹到std :: string

sum(1, 2., 3) 

,它將返回總和的最普遍的類型(在這種情況下 - double)。 問題在於字符。當我這樣稱呼它

sum("Hello", " ", "World!") 

模板參數推導爲const char [7]例如,因此它不會編譯。我找到了指定最後一個參數爲std::string("World!")的方法,但它並不漂亮,有沒有什麼辦法實現自動類型扣除到std::string或正確過載sum

的代碼,我到目前爲止有:

template<typename T1, typename T2> 
auto sum(const T1& t1, const T2& t2) { 
    return t1 + t2; 
} 

template<typename T1, typename... T2> 
auto sum(const T1& t1, const T2&... t2) { 
    return t1 + sum(t2...); 
} 

int main(int argc, char** argv) { 
    auto s1 = sum(1, 2, 3); 
    std::cout << typeid(s1).name() << " " << s1 << std::endl; 

    auto s2 = sum(1, 2.0, 3); 
    std::cout << typeid(s2).name() << " " << s2 << std::endl; 

    auto s3 = sum("Hello", " ", std::string("World!")); 
    std::cout << typeid(s3).name() << " " << s3 << std::endl; 

    /* Won't compile! */ 
    /* 
    auto s4 = sum("Hello", " ", "World!"); 
    std::cout << typeid(s4).name() << " " << s4 << std::endl; 
    */ 

    return 0; 
} 

輸出:

i 6 
d 6 
Ss Hello World! 
+3

您正在使用C++ 14,所以''World!「s'。 –

+0

@ T.C。我試過這[ideone](http://ideone.com/3fRo0M),但我有一個編譯錯誤,我做錯了嗎? – NikolayKondratyev

+1

你需要一個'using namespace std :: literals;'。 –

回答

1

我只想寫一個處理const char*特別簡單的重載身份的功能。

template<typename T> 
decltype(auto) fix(T&& val) 
{ 
    return std::forward<T>(val); 
} 

auto fix(char const* str) 
{ 
    return std::string(str); 
} 

template<typename T1, typename T2> 
auto sum(const T1& t1, const T2& t2) { 
    return fix(t1) + t2; 
} 

template<typename T1, typename... T2> 
auto sum(const T1& t1, const T2&... t2) { 
    return t1 + sum(t2...); 
} 
+0

是否需要使用decltype?我試圖在沒有它的情況下運行你的解決方案,看起來好像工作正常。 – NikolayKondratyev

+0

@尼古拉·康德拉特耶夫:是的,在幾乎所有情況下,它都可以正常工作而不會出現decltype。 decltype只是確保傳入的對象完美地轉發給返回類型。例如,如果您有一個無限制的整數類型來進行動態分配,並且您希望避免不使用'decltype(auto)'而發生的潛在的昂貴副本,那麼這對您可能很重要。或者如果您有一種不可複製的類型(但仍可移動)。 –

1

最終你char指針類型不被雙方的左派右側很好地處理operator +。'如果需要,您可以重載製造中介。

下面我冒昧地將其重構爲單參數支持的sum(不是必需的步驟,但允許sum(x)重載,這更清楚地理解)。希望你明白這個主意。

#include <iostream> 
#include <string> 

// generic identity 
template<typename T1> 
auto sum(const T1& t1) 
{ 
    std::cout << __PRETTY_FUNCTION__ << '\n'; 
    return t1; 
} 

// specialized for const char [N] 
auto sum(const char *s) 
{ 
    std::cout << __PRETTY_FUNCTION__ << '\n'; 
    return std::string(s); 
} 

template<typename T1, typename... T2> 
auto sum(const T1& t1, const T2&... t2) 
{ 
    std::cout << __PRETTY_FUNCTION__ << '\n'; 
    return t1 + sum(t2...); 
} 

int main(int argc, char** argv) { 

    std::cout << sum(1,2,3) << '\n'; 
    std::cout << sum(1, 2.0, 3) << '\n'; 
    std::cout << sum("Hello", " ", std::string("World!")) << '\n'; 
    std::cout << sum("Hello", " ", "World!"); 
    return 0; 
} 

輸出

auto sum(const T1 &, const T2 &...) [T1 = int, T2 = <int, int>] 
auto sum(const T1 &, const T2 &...) [T1 = int, T2 = <int>] 
auto sum(const T1 &) [T1 = int] 
6 
auto sum(const T1 &, const T2 &...) [T1 = int, T2 = <double, int>] 
auto sum(const T1 &, const T2 &...) [T1 = double, T2 = <int>] 
auto sum(const T1 &) [T1 = int] 
6 
auto sum(const T1 &, const T2 &...) [T1 = char [6], T2 = <char [2], std::__1::basic_string<char>>] 
auto sum(const T1 &, const T2 &...) [T1 = char [2], T2 = <std::__1::basic_string<char>>] 
auto sum(const T1 &) [T1 = std::__1::basic_string<char>] 
Hello World! 
auto sum(const T1 &, const T2 &...) [T1 = char [6], T2 = <char [2], char [7]>] 
auto sum(const T1 &, const T2 &...) [T1 = char [2], T2 = <char [7]>] 
auto sum(const char *) 
Hello World! 

祝您好運

相關問題