Как shared_ptr <> безопасно разрешает приведение к bool? - PullRequest
21 голосов
/ 07 июля 2010

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

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

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

Ответы [ 3 ]

34 голосов
/ 07 июля 2010

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

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

explicit operator bool() {
  return m_Ptr != nullptr;
}
5 голосов
/ 07 июля 2010

Трюк работает так.Вы определяете все это внутри вашего типа интеллектуального указателя (в данном случае 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 является частной структурой.Но вызывающий код может использовать это (неявное) преобразование в тип указателя и проверить, является ли он нулевым или нет.Который в C ++ может использоваться как выражение bool.

3 голосов
/ 07 июля 2010

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

...