如何避免在此模板代码中出现有关被零除的警告?

发布于 2024-10-20 12:47:32 字数 1065 浏览 1 评论 0原文

我有一个定点算术类,这是其中的突出部分:

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 似乎做了足够的优化来确定我的一个分支保证除以零,但没有足够的优化来确定该分支保证不运行。

我可以在文件中抛出 #pragma GCC 诊断忽略的“-Wdiv-by-zero”,但这有掩盖真正警告的风险。

处理这种情况的适当方法是什么? (或者我的分析完全错误,并且我确实有一个真正的运行时间除以零?)

I have a class for fixed-point arithmetic, of which this is the salient portion:

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.");
};

On GCC 4.4.5, the following line of code:

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

Generates an error:

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

While there is a division by constant zero in the code - one of T/S or S/T must be zero for unequal scales - if S%T == 0 (and S is not 0), then S/T is not zero. GCC seems to be doing just enough optimization to figure out that one of my branches is guaranteed to divide by zero, but not enough optimization to figure out that branch guaranteed to not run.

I can throw #pragma GCC diagnostic ignored "-Wdiv-by-zero" in the file, but that risks masking real warnings.

What's the appropriate way to handle this situation? (Or is my analysis totally wrong and I do have a real runtime division by zero?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

朦胧时间 2024-10-27 12:47:32

像什么?

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_ 您可以通过参数“专门化”函数。

something like?

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(...);

or using mpl::bool_ you could "specialize" functions through parameters.

爱冒险 2024-10-27 12:47:32

您可以使用支持模板进行除法,并将其专门用于在除数为 0 时硬编码任意值(假定不会使用它)。

You could use a supporting template to do the division, and specialise it to hardcode an arbitrary value (given it won't be used) when the divisor is 0.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文