设置
我正在使用一个名为MotionBuilder的应用程序的应用程序接口。为了访问MotionBuilder属性值,您将其读入一个双精度变量,而不管它实际表示的是哪种数据类型。
下面是我编写的一个实用函数,用于计算标量属性的值:
template <typename DataT>
inline DataT GetScalar(FBProperty& prop, FBEvaluateInfo* evaluateInfo)
{
double data = 0.0;
prop.GetData(&data, sizeof(data), evaluateInfo);
return static_cast<DataT>(data);
}这样,我就可以编写GetScalar<float>(camera.Roll, evaluateInfo)或GetScalar<bool>(camera.Visibility, evaluateInfo),而不是让多行乱七八糟的未初始化缓冲区和类型转换弄乱我的代码。
我在Visual Studio中使用/W4进行编译,并在出现警告时处理所有警告。当我使用GetScalar<bool>时,编译器会生成a C4800 warning
'double' : forcing value to bool 'true' or 'false' (performance warning)当编译器创建GetScalar<bool>时,它会得到一个从double到bool的static_cast,这显然是它不喜欢的。由于我最初的目标是用一个模板函数处理多种类型(布尔型、浮点型、双精度型等),所以我不能只添加通常的!= 0.0。
为了解决这个警告,我有两个选择。
选项1
我可以直接使用语用标记来抑制警告,因为强制转换正在做我想让它做的事情:
template <typename DataT>
inline DataT GetScalar(FBProperty& prop, FBEvaluateInfo* evaluateInfo)
{
double data = 0.0;
prop.GetData(&data, sizeof(data), evaluateInfo);
#pragma warning (push)
#pragma warning (disable: 4800) // Don't complain about casting to bool
return static_cast<DataT>(data);
#pragma warning (pop)
}选项2
我可以添加一个专门化的GetScalar来处理bool:
template <>
inline bool GetScalar<bool>(FBProperty& prop, FBEvaluateInfo* evaluateInfo)
{
double data = 0.0;
prop.GetData(&data, sizeof(data), evaluateInfo);
return data != 0.0;
}问题是
我认为对于一些双x,static_cast<bool>(x)完全等同于x != 0.0。实际上,在发布模式下编译的一个简单测试在两种情况下都会给出相同的汇编输出。那么,为什么C4800自称是“性能警告”呢?上面列出的两个选项在功能上是否相同?如果归结为风格问题,在戴上你最好的书呆子帽子后,你更喜欢哪种选择?
发布于 2013-07-11 05:54:48
这是一个警告,它告诉您此转换可能存在性能问题。既然你想做转换,那就做吧。不要浪费时间为没有任何有用信息的警告编写复杂的变通方法。
发布于 2013-07-11 05:13:13
我确实认为对于bool的情况,与0进行比较比强制转换更具可读性。我还会质疑,拥有一个可以专门用于数值类型和具有相同实现的bool的函数在语义上是否有意义,即使它恰好在这里工作。
一般情况下。在你的特殊情况下,我认为有一个统一的模板很好,如果它避免了代码重复,那就是一个优势。如果有什么不同的话,我可能只会为转换为DataT的部分创建一个函数专门化,而不是整个函数:
template <typename T>
T convertTo(double d) { return static_cast<T>(d); }
template <>
double convertTo<bool>(double d) { return d != 0.0; }
template <typename DataT>
inline DataT GetScalar(FBProperty& prop, FBEvaluateInfo* evaluateInfo)
{
double data = 0.0;
prop.GetData(&data, sizeof(data), evaluateInfo);
return convertTo<DataT>(data);
}或者,您可以有选择地禁用该警告,但如果您这样做了,请在注释中解释为什么这是必要的。
发布于 2013-07-11 05:14:46
我不确定对于您的特定设置最好的解决方案是什么(我认为静态强制转换到bool是非常好的),但是处理分支的通用方法是为每个单独的操作创建单独的特征。在你的例子中,就是"convert_to_bool":
template <typename Out>
struct converter
{
static Out from_double(double x)
{
return static_cast<Out>(x);
}
};
template <>
struct converter<bool>
{
static bool from_double(double x)
{
return x != 0;
}
};现在您可以使用:
return converter<DataT>::from_double(data);通过这种方式,您可以处理主模板中突然出现的每种情况,并且需要对某些类型进行特殊处理,而无需对主模板进行分支。
https://stackoverflow.com/questions/17580890
复制相似问题