Когда я могу использовать явный оператор bool без приведения?

Мой класс имеет явное преобразование в bool:

struct T {
    explicit operator bool() const { return true; }
};

и у меня есть его экземпляр:

T t;

Чтобы назначить его переменной типа bool, мне нужно написать листинг:

bool b = static_cast<bool>(t);
bool b = bool(t);
bool b(t);  // converting initialiser
bool b{static_cast<bool>(t)};

Я знаю, что я могу использовать свой тип непосредственно в условном без литья, несмотря на explicit классификатор:

if (t)
    /* statement */;

Где еще я могу использовать t как bool без трансляции?

Ответ 1

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

Заявления

  • if (t) /* statement */;
    
  • for (;t;) /* statement */;
    
  • while(t) /* statement */;
    
  • do { /* block */ } while (t);
    

Выражение

  • !t
    
  • t && t2
    
  • t || t2
    
  • t ? "true" : "false"
    

Тесты времени компиляции

Для этих операторов должен быть constexpr:

  • static_assert(t);
    
  • noexcept(t)
    

Алгоритмы и понятия

  • NullablePointer T
    

    В любом случае для стандарта требуется тип, удовлетворяющий этому понятию (например, тип pointer a std::unique_ptr), он может быть контекстуально преобразован. Кроме того, возвращаемое значение операторов равенства и неравенства NullablePointer должно быть контекстно конвертируемым в bool.

  • std::remove_if(first, last, [&](auto){ return t; });
    

    В любом алгоритме с параметром шаблона с именем Predicate или BinaryPredicate аргумент предиката может возвращать T.

  • std::sort(first, last, [&](auto){ return t; });
    
    В любом алгоритме с параметром шаблона под названием Compare аргумент компаратора может возвращать T.

(source1, source2)


Помните, что сочетание операторов const и non-const может вызвать путаницу: