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

Mas*_*Man 9 c++ casting

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.


jua*_*nza 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
}
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)


wil*_*llj 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
}
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)