是否符合visual c++std::isfinite()标准
Is visual c++ std::isfinite() standard conforming?
我得到了一个包装类,它有一个到double
的简单而轻量级的隐式转换运算符。
我喜欢使用它,就像我会使用替身一样,例如:
if (!std::isfinite(myVar)) ...
但std::isfinite(double)
的可视化c++实现实际上是一个通过复制获得其论点的模板。
所以我的包装类复制构造函数被调用了,而且它不是轻量级的。
为了避免这种情况,我必须写:
if (!std::isfinite((double)myVar)) ...
对于每个呼叫:(
如果可视化c++std::isfinite()
是在cppreference.com上定义的,我就不必强制执行每个调用:([edit]我可能错了,Integral不是一个实际的类型…但是…[edit>它仍然不应该接受用户定义的类型?(
bool isfinite( float arg );
bool isfinite( double arg );
bool isfinite( long double arg );
bool isfinite( Integral arg );
我不确定这个标准是怎么说的。vc++模板std::isfinite
是否符合标准?
我应该将此报告为Microsoft connect上的错误吗?
我应该定义我自己的isfinite(double)
,调用std::isfinite
吗?
编辑
或者,这可能不是问题,因为在发布版本中,调用被内联,并且没有发生复制?(好吧,我现在就试着检查一下,几分钟后更新(
编辑2
在使用/Ob2(内联任何合适的函数(的版本构建中,它似乎没有内联
编辑3
根据要求,提供样品:
struct DoubleWrapper {
double value;
DoubleWrapper(double value) : value(value) {
printf("copy Ctorn");
}
DoubleWrapper(const DoubleWrapper & that) : value(that.value) {}
operator double() const {
return this->value;
}
};
int main() {
DoubleWrapper a(rand()); //rand to prevent optimization
auto res = std::isfinite(a);
printf("%d", res); //printf to prevent optimization
}
编辑4
因此,根据Ben Voigt的评论,这是我在类标题中添加的内容:
#include <cmath>
namespace std {
inline bool isfinite(const DoubleWrapper<double> & dw) {
return isfinite((double)dw);
}
}
这是一个正确的解决方案吗?
唯一的问题是,我是否应该对所有使用双精度的<cmath>
函数执行相同的操作?
编辑5
我在这里回应Shafik Yaghmour的回答,因为评论太有限了(也许我应该开始一个新的问题(
如果我理解正确,我应该把它添加到我的类标题中,而不是编辑4:
inline bool isfinite(const DoubleWrapper<double> & dw) {
return isfinite((double)dw);
}
using std::isfinite;
是否需要将其放在命名空间中,或者我可以将其保留在"全局"命名空间中?
但这意味着我必须将所有呼叫从std::isfinite(dw)
更改为isfinite(dw)
。
好吧,但我意识到有很多事情我不明白。我很困惑。
我知道在std中添加重载是不允许的。
但是,是否允许添加模板专用化?为什么?这有什么区别?
不管怎样,我试过了,但这并不能解决我的问题,因为这种专业化:
template<> inline __nothrow bool std::isfinite(const MagicTarget<double> & mt) {
return std::isfinite((double)mt);
}
编译器不会选择标准的
template<class _Ty> inline __nothrow bool isfinite(_Ty _X)
{
return (fpclassify(_X) <= 0);
}
要选择,它应该是
template<> inline __nothrow bool std::isfinite(MagicTarget<double> mt) {
return std::isfinite((double)mt);
}
但这仍然会将副本称为Ctor:(
令人惊讶的是,重载(见编辑4(是在标准模板上选择的。。。我开始觉得有些C++规则对我来说太微妙了:(
但是,首先,为什么cmath函数,尤其是std::isfinite
是一个模板?
接受浮点类型的其他东西有什么意义?
无论如何,vc++std::isfinite
调用仅为float、double和long double定义的std::fpclassify
。那么…这有什么意义?
我认为标准委员会把cmath函数作为模板搞砸了。它们应该只为相关的类型定义,或者可能将它们的参数作为通用引用。
就这样,对不起你的咆哮。。。
我会选择(非标准(过载。非常感谢。
通过这些评论,您已经接近最终解决方案,因此,对您的问题进行编辑4。
您不应该将其添加到std
命名空间,而应该将它添加到您自己的命名空间中,并依赖于参数相关的查找。有关更多详细信息,请参阅在c++中的命名空间std中重载数学函数是否是一种好的做法。
考虑到标准委员会显然希望限制cmath
函数只能用算术类型调用,依赖隐式转换不是一个好主意。因此,通过强制转换执行显式转换是所有cmath
函数的安全方法:
isfinite((double)dw)
您可以在将非算术类型作为参数传递给cmath函数有效吗?中找到详细信息?。
- 使用CMake检测支持的C++标准
- 如何理解C++标准N3337中的expr.const.cast子句8
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 编译标准库类型
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 铸造标准::有没有回到原来的类型
- 标准 N3337 5.2.10 第 7 条中的C++"类型"是什么意思?
- this_thread::sleep_for和计时时钟之间的关系是否由C++11标准指定
- 标准库类型的赋值运算符的引用限定符
- 标准是否严格定义了该程序应该如何编译?
- 如何从Windows应用程序输出到标准?
- 安全到标准:移动会员?
- 如何正确将字符串转换为标准::时间::system_clock::time_point?
- 这是否符合C++标准:双响双响,例如!!(-0.0).
- 标准::变体的赋值运算符
- 捕获标准输出以压缩并使用 CTRL-C 中断会给出损坏的 zip 文件
- 如何在 Mac 上使用 c++17 并行标准库算法?
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- 是否符合visual c++std::isfinite()标准