struct Foo {
void setBar(bool bar_) { bar = bar_; }
bool bar;
};
int main() {
Foo f;
f.setBar("true");
}
Run Code Online (Sandbox Code Playgroud)
由于类型转换,上面的代码成功编译,即使在bool
期望a的位置传递char数组.
是否有可能导致此代码编译失败?(C++ 03解决方案首选,因为我工作场所的编译器很古老.)
我已经在StackOverflow上查看了以下相关问题,但它们并没有完全解决这个问题.在C++中防止隐式转换,为什么编译器选择bool over string来隐式转换为L""?
jro*_*rok 10
您可以声明一个接受const char*
和不提供定义的函数:
void setBar(const char*);
Run Code Online (Sandbox Code Playgroud)
这将使其在链接时失败.你仍然会留下所有其他的隐式转换 - 从任何指向bool的指针,bool的整体,浮动到bool ......
另外一个选项:
struct Foo {
void setBar(bool bar_) {}
private:
template<typename T>
void setBar(T bar) {}
};
Run Code Online (Sandbox Code Playgroud)
通过这种方式,如果您使用其他任何方式调用它,您将收到有关它是私有的错误bool
.
一种选择是创建setBar
一个模板,并允许它只用于bool
:
#include <type_traits>
struct Foo
{
template <typename T>
void setBar(T bar_)
{
static_assert(std::is_same<bool,T>::value, "not bool");
bar = bar_;
}
bool bar;
};
int main() {
Foo f;
f.setBar(true); // OK
f.setBar("true"); // Error
f.setBar(1); // Error
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用SFINAE std::enable_if
达到相同的效果,但编译器警告可能不太容易阅读:
struct Foo
{
template<class T ,
class = typename std::enable_if<std::is_same<bool,T>::value>::type >
void setBar(T bar_)
{
bar = bar_;
}
bool bar;
};
Run Code Online (Sandbox Code Playgroud)
有一个共同的习惯用法既可以避免这个问题,也可以提供其他优点.bool
您可以创建一个更清楚地描述其所代表状态的自定义类型,而不是使用它.
该类型bool
仅代表true
或的通用值false
,而在实际使用中,您将这些状态重载为更具体的含义.这是一个使用枚举来定义新类型的示例:
enum Bar { ok, foobar };
struct Foo {
void setBar(Bar bar_) { bar = bar_; }
Bar bar;
};
int main() {
Foo f;
f.setBar(foobar); // ok
f.setBar("true"); // error
}
Run Code Online (Sandbox Code Playgroud)
这仍允许从任何算术或浮动类型进行隐式转换.为了避免这种情况,您可以使用C++ 11 enum class
,或者像这样滚动自己的强类型bool:
template<class Tag>
struct Bool { bool value; };
typedef Bool<struct BarTag> Bar;
const Bar Ok = { false };
const Bar FooBar = { true };
Run Code Online (Sandbox Code Playgroud)