Visual C++ 编译器对转换为bool 发出警告,但带有一个愚蠢的性能警告。通常这是一个不受欢迎的警告,但不幸的是,它不能通过简单的演员阵容来消除。消除它的几乎成语是使用双重否定,!!,bang-bang,例如return !!0.0.
您的问题恰恰相反,您想要这样的警告或错误,但 bang-bang about-idiom 仍然可以成为解决方案的一部分。
使用下面举例说明的想法,您只需在需要布尔值的地方写 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.cpp
foo.cpp:在函数'Bool something()'中:
foo.cpp:43:22:错误:无法将 '0.0' 从 'double' 转换为 'Bool'
{ 返回 TO_BOOL 0.0; } // ΓåÉ Line 43
^
foo.cpp:在函数'double g()'中:
foo.cpp:48:25:错误:请求从“双”转换为非标量类型“布尔”
布尔 x = TO_BOOL 0.0; // ΓåÉ Line 48
^
foo.cpp:50:13: 错误:'operator=' 不匹配(操作数类型为'Bool' 和'double')
x = TO_BOOL f(); // 其中 f() 是一个返回双精度的函数
^
foo.cpp:23:14: 注意: 候选: 模板
Bool& Bool::operator=(T)
自动运算符=( T const 其他 )
^
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 CLEAN
foo.cpp:在函数'int main()'中:
foo.cpp:58:18:警告:建议在 '||' 内的 '&&' 周围加上括号[-括号]
返回 a && b ||某物();
^
c:\my\forums\so\105> g++ foo.cpp -D CLEAN -Wno-括号
c:\我的\论坛\so\105> _
如果您希望不考虑从 Bool 到 bool 以外的其他类型的隐式转换,只需将该转换运算符也设为检查模板,如构造函数和赋值运算符。