如何消除模板代码中的"divide by 0"错误
How to eliminate "divide by 0" error in template code
我正在使用一对整数模板参数来指定比率,因为我不能使用双精度作为模板参数。转换为双精度值时,防止使用三元除以零。这在早期版本的编译器中有效,但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 const
或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;
}
};
对于图像大小调整操作,每个像素至少执行 4 次 k
函数,因此效率至关重要。我希望在编译时知道所有常量,以便编译器可以尽可能简化表达式。
基于接受的答案,我希望创建一个Ratio
模板类,该类将简单地产生两个int
的比率作为constexpr double
,并将其专门用于0, 0
参数。Visual Studio 2013尚未实现constexpr
因此我不相信编译器会将其视为编译时常量。幸运的是,原始三元表达式的变体消除了错误。
相关文章:
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 将 std::thread by 值推送到列表中
- MATLAB to C++: csvread() not supported by MATLAB Coder
- Makefile by ocaml 和 cpp 扩展名
- C++ OpenCV Randu 函数抛出'Integer division by zero'
- 从函数 BY VALUE 返回数组,返回结构时会发生什么?
- 如何在不受其他文件影响的情况下"by itself" Visual Studio 项目中运行C++文件?
- Divide et impera sum of the elements of an array bug
- MacPorts:"Error: clang-4.0 has been replaced by clang-8.0; please install that instead",但我已经安装了clang
- 为什么 c++ 向量没有"delete by index"?
- 这个给定的代码应该将给定的数字转换为尽可能滞后的数字,no.by 用 9.It 替换合适的数字是行不通的
- 传递类 by-value 时,调用方或被调用方是否调用析构函数
- By-ref 参数:这是 std::thread 和 std::bind 之间的不一致吗?
- 转到特定页面后,如何将滑动视图的当前索引设置为选项卡栏"by reference"的当前索引?
- base64 decode with openssl BIO block by block
- 如何在 C++ 中修复"/usr/bin/ld: warning: liblber-2.4.so.2, needed by //usr/lib/x86_64-linux-gnu/libcurl-gnu
- 由mpglib输出的"hip: Can't rewind stream by 74 bits"到底意味着什么?
- 用rvalue参考和变异模板bits bits bys blamda by
- 如何消除模板代码中的"divide by 0"错误
- "potential divide by zero"在 Visual C++ C4723 警告说明中是什么意思?