簡體   English   中英

通過重載部分模板專業化

[英]Partial template specialization by overloading

我創建了一個帶有額外模板參數的簡單圓形模板函數,該參數定義了在返回之前需要將舍入值轉換為的類型。

template <typename T, typename U>
T round(U val) {
    T result;
    if (val >= 0)
        result = (T)(floor(val + (U)(.5)));
    else
        result = (T)(ceil( val - (U)(.5)));
    return result;
}

int a = round<int>(5.5); // = 6
// no compiler warnings

但我也希望留下額外的模板參數,以便您不必插入已添加的類型作為參數。

template <typename T>
T round(T val) {
    return round<T>(val);
}

double b = round(5.5) // = 6.0
// C2668

但是,現在編譯器抱怨:

錯誤C2668:對重載函數的模糊調用

我認為編譯器總是會選擇最具體的模板,這應該是最后一個模板。 為什么不是這種情況,是否有任何變通方法(不是專門針對此輪次函數)?


模糊的調用並沒有指向round(5.5)而是指向return round<T>(val); 因此,這個問題的答案是將重載函數的返回值重寫為

return round<T,T>(val);

這解決了這個問題。

感謝galop1n 回答 我的其他問題

您收到錯誤,因為在模板參數扣除期間不會推斷返回類型。 相反,它們可以從推導出的函數參數中替換。 因為兩個重載具有相同的參數推導,所以過載資源是不明確的,這給出了編譯器錯誤。

在C ++ 11中,您可以為函數模板定義默認模板參數。 如果添加一個額外的默認函數參數等於默認返回值,除非顯式傳遞默認返回值,否則總是將參數類型作為返回類型獲取:

#include <iostream>
#include <cmath>
#include <type_traits>

template <typename T, typename Ret = T>
Ret xround(T val, Ret ret = Ret()) {
    return static_cast<Ret>(
        (val >= 0) ?
        floor(val + (T)(.5)) :
        ceil( val - (T)(.5))
    );
}

int main()
{
    auto a = xround(5.5, int()); // = 6
    static_assert(std::is_same<decltype(a), int>::value, "");
    std::cout << a << "\n";       

    auto b = xround(5.5); // = 6.0
    static_assert(std::is_same<decltype(b), double>::value, "");
    std::cout << b << "\n";
}   

實例

請注意,我使用了三元運算符而不是if-else ,並且我將函數重命名為xround因為在C ++ 11中已經有一個round <cmath> (當然你也可以使用)。

注意 :臨時類似於標簽分派:它完全用於確定返回類型,實際的臨時應由編譯器優化。

您的問題不是模板專業化,而是過載模糊。

這是類似的:

int fn(int) { return 0; }
// error: new declaration ‘double fn(int)’
// error: ambiguates old declaration ‘int fn(int)’
double fn(int) { return 0; }

有一個模板,其中U有T作為默認參數將不會做得更好:

template <typename T, typename U = T>
T fn(U val) {
    return T();
}

int main() {
    // error: no matching function for call to ‘fn(double)’
    // note: template argument deduction/substitution failed:
    double d = fn(1.5); // fn<double>(1.5) will work
}

並且不允許部分專業化:

template <typename T, typename U>
T fn(U val) {
    return T();
}

// error: function template partial specialization ‘fn<T, T>’ is not allowed
template <typename T>
T fn<T, T>(T val) {
    return T();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM