这是我第二次犯大错误,通过创建一个布尔类型的变量而不是双精度。例如,考虑
double f()
{
return true;
}
bool something()
{
return 0.0;
}
double g()
{
bool x = 0.0; // (1)
if (something()) {
x = f(); // where f() is a function returning a double
}
return x;
}
我认为编译器应该告诉我这很糟糕,但我的编译器 (g++) 不会发出带有 -Wall 的小警告......它会导致稍后的测试错误。gcc/g++ 是否有一些选项可以发出警告(例如在第 1 行,这显然是不好的)?
您可以使用统一初始化来获取错误:
bool x{0.0};
错误:在初始值设定项列表中,类型"double"无法缩小为"bool" [-Wc++11-narrowing]
它也可以用于分配:x = {f()};
和返回return {x};
。
虽然我没有直接的答案(要求编译器警告),但我确实有一个不透明的 typedef 库,其中包含一个"inconvertibool"类型,它与布尔类似,但不适用于其他类型,如 int 或 double。 它为示例中的情况提供了编译时错误:
foo.cpp: In function 'double f()':
foo.cpp:5:31: error: cannot convert 'inconvertibool {aka opaque::inconvertibool}' to 'double' in return
return inconvertibool(true);
^
foo.cpp: In function 'inconvertibool something()':
foo.cpp:9:12: error: could not convert '0.0' from 'double' to 'inconvertibool {aka opaque::inconvertibool}'
return 0.0;
^
foo.cpp: In function 'double g()':
foo.cpp:13:23: error: conversion from 'double' to non-scalar type 'inconvertibool {aka opaque::inconvertibool}' requested
inconvertibool x = 0.0; // (1)
^
foo.cpp:15:9: error: no match for 'operator=' (operand types are 'inconvertibool {aka opaque::inconvertibool}' and 'double')
x = f(); // where f() is a function returning a double
^
当然,这只有在您始终使用这种类型而不是 bool 时才有帮助,但它与您的场景不太匹配,因为您说你的意思是"双精度",而不是"bool"。
Visual C++ 编译器警告转换为 bool
的,但有一个愚蠢的性能警告。通常这是一个不受欢迎的警告,但不幸的是,它不能用简单的演员表来静音。沉默它的近乎成语是使用双重否定, !!
,砰,例如 return !!0.0
.
你的问题是相反的,你想要这样的警告或错误,但仍然砰几乎成语可以成为解决方案的一部分。
有了下面举例说明的想法,您只需编写Bool
而不是bool
您想要布尔值的位置,并使用!!
来确保干净的bool
值,否则您会收到编译错误。
这样做的好处是,您很可能可以在代码中进行全局搜索和替换,将bool
替换为Bool
。
#ifdef CLEAN
# define TO_BOOL !!
#else
# define TO_BOOL
#endif
#define STATIC_ASSERT( e ) static_assert( e, #e )
#include <type_traits> // std::is_same
#include <utility> // std::enable_if_t
class Bool
{
private:
bool value_;
public:
operator bool() const { return value_; }
template< class T
, class Enabled_ = std::enable_if_t<std::is_same<T,bool>::value, void>
>
auto operator=( T const other )
-> Bool&
{ value_ = other; return *this; }
Bool(): value_() {}
template< class T
, class Enabled_ = std::enable_if_t<std::is_same<T,bool>::value, void>
>
Bool( T const value )
: value_( value )
{}
};
auto f()
-> double
{ return 0.0; }
auto something()
-> Bool
{ return TO_BOOL 0.0; } // ← Line 43
auto g()
-> double
{
Bool x = TO_BOOL 0.0; // ← Line 48
if (something()) {
x = TO_BOOL f(); // where f() is a function returning a double
}
return x;
}
auto main() -> int
{
Bool a, b, c;
return a && b || something();
}
使用 g++ 进行编译的示例:
C:\my\forums\so\105> g++ foo.cppfoo.cpp:在函数 'Bool something()' 中:foo.cpp:43:22:错误:无法将"0.0"从"双精度"转换为"布尔" { 返回 TO_BOOL 0.0; } ΓåÉ 43号线 ^foo.cpp:在函数'double g()'中:foo.cpp:48:25:错误:请求从"双精度"转换为非标量类型"Bool" 布尔值 x = TO_BOOL 0.0; ΓåÉ 48号线 ^foo.cpp:50:13:错误:与"运算符="不匹配(操作数类型为"布尔"和"双精度") x = TO_BOOL f(); 其中 f() 是一个返回双精度的函数 ^foo.cpp:23:14:注意:候选:模板<类T,类Enabled_> Bool& Bool::operator=(T) 自动运算符=( T 常量其他 ) ^foo.cpp:23:14:注意:模板参数推导/替换失败:foo.cpp:12:11: 注意:候选人:Bool& Bool::operator=(const Bool&) 类布尔值 ^foo.cpp:12:11:注意:参数 1 没有已知的从"double"到 'const Bool&' 的转换foo.cpp:12:11: 注意:候选人:Bool& Bool::operator=(Bool&&)foo.cpp:12:11:注意:参数 1 没有已知的从"double"到 'Bool&&' 的转换foo.cpp: 在函数 'int main()' 中:foo.cpp:58:18:警告:建议在"||"中的"&&"两边加上括号[-括号] 返回 A && B ||某物(); ^c:\my\forums\so\105> g++ foo.cpp -D CLEANfoo.cpp: 在函数 'int main()' 中:foo.cpp:58:18:警告:建议在"||"中的"&&"两边加上括号[-括号] 返回 A && B ||某物(); ^c:\my\forums\so\105> g++ foo.cpp -D CLEAN -Wno-括号c:\my\forums\so\105> _
如果您希望不考虑从 Bool
到bool
以外的其他类型的隐式转换,只需将该转换运算符也设置为选中的模板,如构造函数和赋值运算符。
在 c++ 中,强制编码人员自己处理类型,为运行时释放资源。价格是跟踪类型,但好处是效率和速度。
这是一个很小的代价,但回报是能够在更短的时间内做更多的事情。