Подтвердить что ты не робот

Как shared_ptr <> безопасно разрешить кастинг для bool?

Я изучал, как std::tr1::shared_ptr<> предоставляет возможность отбрасывать в bool. Я был пойман в прошлом, пытаясь создать умный указатель, который можно отличить до bool как тривиальное решение, т.е.

operator bool() {
  return m_Ptr!=0;
}

обычно заканчивается тем, что он неявным образом применяется к типу указателя (предположительно по типу продвижения), что обычно нежелательно. Как реализация boost, так и Microsoft используют трюк, включающий литье в unspecified_bool_type(). Может ли кто-нибудь объяснить, как работает этот механизм, и как он предотвращает неявное литье на основной тип указателя?

4b9b3361

Ответ 1

Техника, описанная в вопросе, это безопасная идиома bool.

С С++ 11 эта идиома больше не нужна. Современное решение проблемы заключается в использовании ключевого слова explicit для оператора:

explicit operator bool() {
  return m_Ptr != nullptr;
}

Ответ 2

Трюк работает так. Вы определяете все это внутри вашего типа интеллектуального указателя (в данном случае shared_ptr):

private:

  struct Tester
  {
    Tester(int) {}  // No default constructor
    void dummy() {}
  };

  typedef void (Tester::*unspecified_bool_type)();

public:

  operator unspecified_bool_type() const
  {
    return !ptr_ ? 0 : &Tester::dummy;
  }

ptr_ - это внутренний указатель внутри класса интеллектуального указателя.

Как вы можете видеть, unspecified_bool_type - это typedef для типа, к которому не может получить доступ какой-либо внешний код, поскольку Tester является частной структурой. Но вызывающий код может использовать это (неявное) преобразование в тип указателя и проверять, является ли оно нулевым или нет. Которая в С++ может использоваться как выражение bool.

Ответ 3

Обычно то, что он возвращает, является указателем на член. Элементы-указатели можно рассматривать как a bool, но не поддерживают многие из неявных преобразований, которые bool делает.