簡體   English   中英

為什么編譯器不能推導出這個簡單函數的模板參數?

[英]Why can't the compiler deduce template argument for this simple function?

這是一個非常簡單的模板問題(我認為對C ++專家來說很簡單),涉及制作通用數學函數。 我有一個簡單的Epsilon函數,如下所示:

template<class T>
static T Epsilon()
{
    return std::numeric_limits<T>::Min();
}

我想將它分配給一些變量,如下所示:

float epsilon = Math::Epsilon();

,唉,我收到編譯錯誤:

錯誤C2783:'T Math :: Epsilon(void)':無法推斷'T'的模板參數

我可以像這樣分配它,沒有錯誤:

float epsilon = Math::Epsilon<float>();

我以為模板引擎能夠看到我的T是“浮動”,但顯然它不能。 我在這里沒有理解什么?

問題是C ++沒有完整的Hindley-Milner演繹算法。 相反,它從函數參數中推導出模板參數

您的函數沒有參數,因此無法推導出模板參數。

模板參數推導僅適用於函數參數,而不適用於返回類型。 這是類似的,因為你不能在返回類型上重載函數(原因很簡單,你不允許使用返回的值,並且在這種情況下編譯器無法推斷出相應的函數)。

通常,函數模板參數僅基於參數中的類型推斷。 沒有爭論,沒有扣除。 要解決此問題,您需要讓編譯器推導出轉換。 像這樣的東西,例如:

struct Epsilon
{
    template <typename T>
    operator T() const
    {
        return std::numeric_limits<T>::min();
    }
};

在這種情況下,對Epsilon的調用實際上創建了一個對象,它可以隱式轉換為目標類型; 當編譯器查找轉換時,而不是在它嘗試調用“函數”時,將進行推導。

您的方法存在根本問題。

返回值不是函數簽名的一部分。 這意味着只能有一個具有該返回值的函數。

要理解,請嘗試編譯

float epsilon = Math::Epsilon<float>();
int epsilon = Math::Epsilon<int>();

它不起作用,因為函數具有相同的簽名。

看一下C ++ 11中的std::numeric_limits來制作一個工作模板。 但是不能推導出模板參數,因為它首先必須被評估然后才能被分配。

我不建議你這樣做,但是如果你真的需要從返回值epsilon中推斷出類型,你可以這樣做:

float epsilon{};
epsilon = Math::Epsilon<decltype(epsilon)>();

可以推導出返回的值類型。 如果您想避免冗余並使用單個float ,您還可以執行以下操作:

auto e = Epsilon<float>();

暫無
暫無

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

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