8

私は固定小数点演算のクラスを持っていますが、これが重要な部分です。

template <typename I, I S>
struct fixed
{
    I value;

    fixed(I i) : value(i * S) {}

    template <typename J, J T> fixed(const fixed<J, T> &fx)
    {
        if (S % T == 0)
            value = fx.value * (S / T);
        else if (T % S == 0)
            value = fx.value / (T / S);
        else
            value = S * fx.value / T;
    }

    static_assert(S >= 1, "Fixed-point scales must be at least 1.");
};

GCC 4.4.5では、次のコード行があります。

fixed<int, 8> f = fixed<int, 2>(1);

エラーを生成します:

fixed.hpp: In constructor ‘fixed<I, S>::fixed(const fixed<J, T>&) [with J = int, J T =     2, I = int, I S = 8]’:
fixed.hpp:81: error: division by zero

コードには定数ゼロによる除算がありますが(スケールが等しくない場合はT/SまたはS/Tのいずれかがゼロである必要があります)、S%T == 0(およびSが0でない)の場合、S/Tはゼロではありません。GCCは、私のブランチの1つがゼロ除算であることが保証されていることを理解するのに十分な最適化を行っているようですが、そのブランチが実行されないことが保証されていることを理解するのに十分な最適化ではありません。

ファイルをスロー#pragma GCC diagnostic ignored "-Wdiv-by-zero"することはできますが、実際の警告を隠すリスクがあります。

この状況に対処するための適切な方法は何ですか?(または、私の分析は完全に間違っていて、実際の実行時のゼロ除算はありますか?)

4

2 に答える 2

7

何かのようなもの?

template<int,int>
struct helper {
    static int apply(...) { return S * fx.value / T; }
};

template<int n>
struct helper<0,n> { // need 0,0 as well to avoid ambiguity
    static int apply(...) { return fx.value * (S / T); }
};

template<int m>
struct helper<m,0> {
    static int apply(...) { return fx.value / (T / S); }
};

helper<(S % T == 0), (T % S == 0)>::apply(...);

またはmpl::bool_、パラメーターを使用して関数を「特殊化」できます。

于 2011-03-07T09:33:03.077 に答える
0

サポート テンプレートを使用して除算を行い、それを特殊化して、除数が 0 の場合に任意の値 (使用されない場合) をハードコードすることができます。

于 2011-03-07T09:37:28.880 に答える