开发者

C++ safe boolean idiom cannot compile with Visual C++ 10(2010)

开发者 https://www.devze.com 2023-01-30 06:22 出处:网络
Hey guys, I have derived my class from the C++ safe bool idiom class from this p开发者_运维知识库age : The Safe Bool Idiom by Bjorn Karlsson

Hey guys, I have derived my class from the C++ safe bool idiom class from this p开发者_运维知识库age : The Safe Bool Idiom by Bjorn Karlsson

class Element : public safe_bool<>
{
public:
    bool Exists() const;
    // boolean_test() is a safe_bool method
    bool boolean_test() const { return Exists(); }; 
};

When I tried to use it in the if expression like below

Element ele;
...
if(ele)

I got an error C2451: conditional expression of type 'Element' is illegal. If I try to cast it to bool like below, I got this error

Element ele;
...
if((bool)ele)

error C2440: 'type cast' : cannot convert from 'Element' to 'bool'

This is the 1st time I am using safe bool idiom, I am not sure if this is not allowed or a bug in Visual C++ 10. Any comments? Thanks in advance!


The safe bool idiom is allowed, although I typically write it like this:

class Element
{
public:
    bool Exists() const;

    /* Begin Safe Bool Idiom */

private:
    // This is a typedef for pointer to an int member of Element.
    typedef int Element::*SafeBoolType;
public:
    inline operator SafeBoolType() const
        { return Exists() ? &Element::someDataMember : 0; }
    inline bool operator!() const
        { return !Exists(); }

    /* End Safe Bool Idiom */

private:
    int someDataMember; // Pick any data member
    // ...
};

This how I've seen it implemented. In fact, Boost implements the idiom in this manner for the smart pointer classes (using an include file).


It doesn't seem to compile with any compiler. Apparently safe_bool cannot return the address of a protected method in its base. You should add a public method to safe_bool_base and return the address of that.

Also, it seems that operators == and != are disabled using a non-dependent construct (may cause an error even if not instantiated).

Perhaps this fixes things:

 class safe_bool_base {
  protected:
    typedef void (safe_bool_base::*bool_type)() const;
  private:
    void cannot_compare_boolean_results() const {}
  public:
    void public_func() const {}
  protected:
    safe_bool_base() {}
    safe_bool_base(const safe_bool_base&) {}
    safe_bool_base& operator=(const safe_bool_base&) {return *this;}
    ~safe_bool_base() {}
  };

  template <typename T=void> class safe_bool : public safe_bool_base {
  public:
    operator bool_type() const {
      return (static_cast<const T*>(this))->boolean_test()
        ? &safe_bool_base::public_func : 0;
    }
  protected:
    ~safe_bool() {}
  };

  template<> class safe_bool<void> : public safe_bool_base {
  public:
    operator bool_type() const {
      return boolean_test()==true ? 
        &safe_bool_base::public_func : 0;
    }
  protected:
    virtual bool boolean_test() const=0;
    virtual ~safe_bool() {}
  };

  template <typename T, typename U> 
    bool operator==(const safe_bool<T>& lhs,const safe_bool<U>& rhs) {
      lhs.cannot_compare_boolean_results(); //call private method to produce error
      return false;
  }

  template <typename T,typename U> 
  bool operator!=(const safe_bool<T>& lhs,const safe_bool<U>& rhs) {
    lhs.cannot_compare_boolean_results(); //call private method to produce error
    return false;   
  }
0

精彩评论

暂无评论...
验证码 换一张
取 消