我有一个包装类,它有一个简单且加权轻量级的隐式转换运算符double
。
我喜欢使用它,因为我会使用double,例如:
if (!std::isfinite(myVar)) ...
但std::isfinite(double)
的visual c ++实现实际上是一个通过副本获取其参数的模板。
所以我的包装类复制构造函数被调用,并且它不是轻量级的。
为避免这种情况,我必须写:
if (!std::isfinite((double)myVar)) ...
每次通话:
如果visual c ++ std::isfinite()
被定义为cppreference.com,我就不必每次调用:([编辑]我可能错了,Integral isn& #39; t实际类型......但是...... [编辑]它仍然不应该接受用户定义的类型?)
bool isfinite( float arg );
bool isfinite( double arg );
bool isfinite( long double arg );
bool isfinite( Integral arg );
我不确定标准对此有何看法。
vc ++模板std::isfinite
是否符合标准?
我应该将此报告为Microsoft connect上的错误吗?
我应该定义自己调用isfinite(double)
的{{1}}吗?
或许这是一个非问题,因为在发布版本中调用内联并且没有复制? (好吧,我现在尝试检查并在几分钟后更新)
在使用/ Ob2(内联任何合适的函数)的发布版本中似乎没有内联
根据要求提供样本:
std::isfinite
所以,根据Ben Voigt的评论,这就是我在课程标题中添加的内容:
struct DoubleWrapper {
double value;
DoubleWrapper(double value) : value(value) {
printf("copy Ctor\n");
}
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
}
这是正确的解决方案吗?
唯一的问题是,对于所有需要加倍的#include <cmath>
namespace std {
inline bool isfinite(const DoubleWrapper<double> & dw) {
return isfinite((double)dw);
}
}
函数,我应该这样做吗?
我在这里回答Shafik Yaghmour的回答,因为评论太有限了(也许我应该开始一个新问题)
如果我理解正确,而不是我的编辑4,我应该将其添加到我的班级标题中:
<cmath>
是否需要将其放在命名空间中,或者我可以将其保留在&#34; global&#34;命名空间?
但这意味着我必须将所有来电从inline bool isfinite(const DoubleWrapper<double> & dw) {
return isfinite((double)dw);
}
using std::isfinite;
更改为std::isfinite(dw)
。
好的,但我发现有许多事情我不明白。 我很困惑。
我知道不允许在std中添加重载。
但是,允许添加模板专业化?为什么?它有什么不同?
无论如何,我试过了,这不是我问题的解决方案,因为这个专业化:
isfinite(dw)
编译器不会在标准编译器上选择:
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);
}
但是这仍然会称副本为Ctor :(
令人惊讶的是,在标准模板上选择了过载(参见编辑4)... 我开始认为一些C ++规则对我来说太微妙了:(
但是,首先,为什么地球上有cmath函数,尤其是template<> inline __nothrow bool std::isfinite(MagicTarget<double> mt) {
return std::isfinite((double)mt);
}
模板?
接受浮点类型的其他任何事情是什么意思?
无论如何,vc ++ std::isfinite
调用std::isfinite
只为float,double和long double定义。
那么......重点是什么?
我认为标准委员会通过允许cmath函数作为模板搞砸了。它们只应针对相关类型定义,或者可以将其参数作为通用引用。
那是它,对不起咆哮......
我会去(不是std)重载。 谢谢!
答案 0 :(得分:3)
通过评论解决您的问题的编辑问题4,您已接近最终解决方案。
您不应将其添加到std
命名空间,您应该将其添加到您自己的命名空间之一,rely on argument dependent lookup请参阅Is it a good practice to overload math functions in namespace std in c++以获取更多详细信息。
鉴于标准委员会明显希望限制仅使用算术类型调用cmath
函数,依赖隐式转换并不是一个好主意。因此,通过强制转换执行显式转换是实现所有cmath
函数的安全方法:
isfinite((double)dw)
您可以在Is it valid to pass non-arithmetic types as arguments to cmath functions?。
中找到详细信息