struct Foo {
void setBar(bool bar_) { bar = bar_; }
bool bar;
};
int main() {
Foo f;
f.setBar("true");
}
上面的代码由于类型转换而成功编译,即使在期望bool
的情况下传递了char数组。
是否可能导致此代码编译失败? (C ++ 03解决方案首选,因为我工作场所的编译器很古老。)
我已经在StackOverflow上查看了以下相关问题,但它们并没有完全解决这个问题。 Preventing implicit conversion in C++,Why does the compiler choose bool over string for implicit typecast of L""?
答案 0 :(得分:10)
您可以声明一个取const char*
且不提供定义的函数:
void setBar(const char*);
这会使它在链接时失败。你仍然会留下所有其他隐式转换 - 从任何指向bool的指针,bool的整体,浮动到bool ......
另一种选择:
struct Foo {
void setBar(bool bar_) {}
private:
template<typename T>
void setBar(T bar) {}
};
这样,如果您使用bool
之外的其他内容调用它,则会收到有关私有内容的错误。
答案 1 :(得分:7)
一种选择是将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
}
或者,您可以将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;
};
答案 2 :(得分:5)
有一个共同的习惯用法既可以避免这个问题,也可以提供其他优点。您可以创建一个更清楚地描述其所代表状态的自定义类型,而不是使用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
}
这仍允许从任何算术或浮动类型进行隐式转换。为了避免这种情况,你可以使用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 };