10
struct Foo {
  void setBar(bool bar_) { bar = bar_; }
  bool bar;
};

int main() {
  Foo f;
  f.setBar("true");
}

由于类型转换,上述代码编译成功,即使在bool预期 a 的地方传递了一个 char 数组。

是否有可能导致此代码编译失败?(首选 C++03 解决方案,因为我工作场所的编译器很古老。)

我在 StackOverflow 上查看了以下相关问题,但它们并没有完全解决这个问题。防止 C++ 中的隐式转换为什么编译器选择 bool 而不是字符串来进行 L"" 的隐式类型转换?

4

3 回答 3

12

您可以声明一个接受const char*但不提供定义的函数:

void setBar(const char*);

这将使其在链接时失败。但是,您仍然需要进行所有其他隐式转换 - 从任何指向 bool 的指针、从整数到 bool、从浮点数到 bool...

另外的选择:

struct Foo {
  void setBar(bool bar_) {}
private:
  template<typename T>
  void setBar(T bar) {}
};

这样,如果您使用除bool.

于 2013-08-27T11:22:29.337 回答
9

一种选择是制作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
}

或者,您可以使用 SFINAEstd::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;
};
于 2013-08-27T11:29:15.517 回答
6

有一个常见的习语既可以避免这个问题,又可以提供其他优势。bool您可以创建一个自定义类型来更清楚地描述它所代表的状态,而不是使用。

该类型仅表示orbool的通用值,而在实际使用中,您正在重载这些状态以表示更具体的内容。这是一个使用枚举定义新类型的示例: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,或者像这样滚动您自己的强类型布尔值:

template<class Tag>
struct Bool { bool value; };

typedef Bool<struct BarTag> Bar;
const Bar Ok = { false };
const Bar FooBar = { true };
于 2013-08-27T14:04:03.460 回答