如何防止从char数组到bool的隐式转换

时间:2013-08-27 11:18:48

标签: c++ casting

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""?

3 个答案:

答案 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仅代表truefalse的通用值,而在实际使用中,您将这些状态重载为更具体的含义。以下是使用枚举定义新类型的示例:

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 };