How to prevent implicit conversion from char array to bool

匿名 (未验证) 提交于 2019-12-03 03:06:01

问题:

struct Foo {   void setBar(bool bar_) { bar = bar_; }   bool bar; };  int main() {   Foo f;   f.setBar("true"); } 

The above code compiles successfully due to type conversion, even though a char array is passed where a bool is expected.

Is it possible to cause this code to fail compilation? (C++03 solution preferred, since the compiler at my workplace is ancient.)

I have looked at the following related questions on StackOverflow, but they don't quite address this problem. Preventing implicit conversion in C++, Why does the compiler choose bool over string for implicit typecast of L""?

回答1:

You can declare a function that takes const char* and don't provide a definition:

void setBar(const char*); 

This will make it fail at link time. You're still left will all other implicit conversion, though - from any pointer to bool, integral to bool, floats to bool...

Another option:

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

This way you'll get an error about it being private if you call it with anything else than bool.



回答2:

One option would be to make setBar a template, and allow it only to work with 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 } 

Alternatively, you can use SFINAE with std::enable_if to the same effect, although the compiler warning might be less easy to read:

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


回答3:

There is a common idiom that both avoids this issue and provides other advantages. Instead of using bool, you can create a custom type that more clearly describes the state that it represents.

The type bool represents only a generic value of true or false, while in actual usage you are overloading these states to mean something more specific. Here's an example using an enum to define a new type:

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 } 

This still allows implicit conversion from any arithmetic or floating type. To avoid this, you can use C++11's enum class, or roll your own strongly-typed bool like this:

template<class Tag> struct Bool { bool value; };  typedef Bool<struct BarTag> Bar; const Bar Ok = { false }; const Bar FooBar = { true }; 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!