Безопасная логическая идиома C ++ не может быть скомпилирована с Visual C ++ 10 (2010) - PullRequest
1 голос
/ 14 декабря 2010

Эй, ребята, я вывел свой класс из класса идиомы безопасного булла C ++ с этой страницы: Идиома безопасного була Бьорна Карлссона

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

Когда я пытался его использоватьв выражении if, как показано ниже

Element ele;
...
if(ele)

Я получил ошибку C2451: условное выражение типа 'Элемент' недопустимо .Если я пытаюсь привести его к типу bool, как показано ниже, я получаю эту ошибку

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

ошибка C2440: «приведение типа»: невозможно преобразовать «Элемент» в «bool»

Это первый раз, когда я использую безопасный bool idiom, я не уверен, что это запрещено или ошибка в Visual C ++ 10. Есть комментарии?Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 14 декабря 2010

Идиома безопасного bool разрешена, хотя я обычно пишу это так:

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

Вот как я это реализовал.Фактически Boost реализует идиому таким образом для классов интеллектуальных указателей ( с использованием включаемого файла ).

0 голосов
/ 14 декабря 2010

Кажется, он не компилируется ни с каким компилятором. Очевидно, safe_bool не может вернуть адрес защищенного метода в своей базе. Вы должны добавить публичный метод к safe_bool_base и вернуть адрес этого.

Также кажется, что операторы == и != отключены с помощью независимой конструкции (может вызвать ошибку, даже если не создан).

Возможно, это исправляет вещи:

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