【问题标题】:How can I avoid a warning about division-by-zero in this template code?如何避免在此模板代码中出现关于除零的警告?
【发布时间】:2011-03-07 09:15:14
【问题描述】:

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

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 diagnostic ignored "-Wdiv-by-zero",但这有可能掩盖真正的警告。

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

【问题讨论】:

  • 如果T % S == 0 不是fx.value / (T / S);S * fx.value / T 一样吗?
  • 有趣。我试过VC。常量 int b = 0;整数 a = 3/b; /*错误*/。常量 int b = 0; if (b!=0) int a = 3/b; /*还是报错,有时候只是笨编译器的问题..*/
  • @LumpN:只有当你有无限的精度来存储中间结果时。
  • @user534498:我也没有尝试过VC,但这些是模板参数而不是变量。变量情况下的警告让我觉得是合理的,因为如果已知 b 始终为零,那么整个分支是不必要的。所以也许 VC 吐出了错误的错误,但我认为为此发出警告/错误仍然很好。

标签: c++ templates g++ integer-division


【解决方案1】:

类似的东西?

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2018-09-30
      • 2016-08-21
      • 1970-01-01
      • 2018-12-04
      • 2015-04-18
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      • 2013-07-27
      相关资源
      最近更新 更多