簡體   English   中英

如何消除模板代碼中的“除以0”錯誤

[英]How to eliminate “divide by 0” error in template code

我使用一對整數模板參數來指定比率,因為我不能使用double作為模板參數。 轉換為雙精度可以防止零三進制。 這在早期版本的編譯器中有效,但Visual Studio 2013出現錯誤:

error C2124: divide or mod by zero

這是代碼的簡化版本:

template<int B1, int B2>
class MyClass
{
    const double B = (B2 == 0) ? 0.0 : (double) B1 / (double) B2;
    // ...
};

MyClass<0, 0> myobj;

我真的希望B能夠在它為零時使用它的表達式進行優化,所以我需要單行定義。 我知道我可以使用模板參數<0, 1>繞過它,但我想知道是否有辦法讓編譯器相信我的表達式是安全的?

我被告知的工作:

 const double B = (B2 == 0 ? 0.0 : (double) B1) /
                  (B2 == 0 ? 1.0 : (double) B2);

這避免了依賴短路評估來防止除以0; 在分割之前進行條件選擇。


最初的想法/也許是這樣的......? (我認為B應該是static constconstexpr ,但我相信你可以constexpr進行排序......)

template<int B1, int B2>
struct MyClass
{
    const double B = (double) B1 / (double) B2;
};

template <int B1>
struct MyClass<B1, 0>
{
    const double B = 0.0;
};

如果你想在MyClass有很多其他東西並且不想復制或放入基礎等,你可以使用上面的專業化方法將B計算移動到支持模板中。

Visual Studio在編譯時無法在三元運算中對B1,B2進行類型轉換,但顯式轉換將起作用。

template<int B1, int B2>
class MyClass
{
    double d1 = (double)B1;
    double d2 = (double)B2;
    const double B = (B2 == 0) ? 0.0 : d1/d2;
    // ...
};

MyClass<0, 0> myobj;

對於好奇 - 這是我最終得到的代碼。 它可能有助於在現實世界中看到它。

template<int B1, int B2, int C1, int C2>
class BicubicFilter
{
    // Based on the formula published by Don Mitchell and Arun Netravali at
    // http://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf
public:
    BicubicFilter() : m_dMultiplier(1.0) {}
    double m_dMultiplier;
    double k(double x) const
    {
        const double B = (double) B1 / ((B2 == 0) ? 1.0 : (double) B2);
        const double C = (double) C1 / ((C2 == 0) ? 1.0 : (double) C2);
        x = fabs(x) * m_dMultiplier;
        if (x < 1.0)
            return ((2.0 - 1.5*B - C) * x*x*x) + ((-3.0 + 2.0*B + C) * x*x) + (1.0 - (2.0/6.0)*B);
        if (x < 2.0)
            return (((-1.0/6.0)*B - C) * x*x*x) + ((B + 5.0*C) * x*x) + ((-2.0*B - 8.0*C) * x) + ((8.0/6.0)*B + 4.0*C);
        return 0.0;
    }
};

對於圖像大小調整操作, k函數每像素執行至少4次,因此效率是關鍵的。 我想在編譯時知道所有常量,因此編譯器可以盡可能地簡化表達式。

根據接受的答案,我曾希望創建一個Ratio模板類,它只能生成兩個int作為constexpr double的比例,並將其專門用於0, 0參數。 Visual Studio 2013尚未實現constexpr因此我不相信編譯器會將其視為編譯時常量。 幸運的是,原始三元表達式的變化消除了錯誤。

暫無
暫無

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

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