Как shared_ptr <> безопасно разрешить кастинг для bool?
Я изучал, как std::tr1::shared_ptr<>
предоставляет возможность отбрасывать в bool. Я был пойман в прошлом, пытаясь создать умный указатель, который можно отличить до bool как тривиальное решение, т.е.
operator bool() {
return m_Ptr!=0;
}
обычно заканчивается тем, что он неявным образом применяется к типу указателя (предположительно по типу продвижения), что обычно нежелательно. Как реализация boost, так и Microsoft используют трюк, включающий литье в unspecified_bool_type()
. Может ли кто-нибудь объяснить, как работает этот механизм, и как он предотвращает неявное литье на основной тип указателя?
Ответы
Ответ 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
делает.