Рассмотрим следующий код:
class Truth
{
public:
Truth(bool val) : value(val) {}
bool operator!() {std::cout<<"operator!()"<<std::endl; return !value;}
operator bool() {std::cout<<"operator bool()"<<std::endl; return value;}
private:
bool value;
};
int main()
{
Truth t(true);
if(!t)
std::cout<<"t is false"<<std::endl;
else
std::cout<<"t is true"<<std::endl;
if(!!t)
std::cout<<"t is false"<<std::endl;
else
std::cout<<"t is true"<<std::endl;
if(t)
std::cout<<"t is false"<<std::endl;
else
std::cout<<"t is true"<<std::endl;
return 0;
}
В заявлениях if(!t)
а также if(!!t)
перегруженный operator!()
реализация вызывается, тогда как (не удивительно) в заявлении if(t)
перегруженный operator bool()
реализация вызывается вместо.
Однако если operator!()
реализация закомментирована, во всех 3 утверждениях, operator bool()
вызывается.
Я понимаю, «почему» это происходит, но меня беспокоит то, что перегрузка логического оператора НЕ (!), По-видимому, пропускает половину семантики оценки истинности, в то время как bool
оператор приведения типов, кажется, хорошо их охватывает.
Я что-то упустил или следует не поощрять перегрузку логического оператора NOT в пользу приведения типа bool?
В C ++ 11 вы можете просто перегрузить explicit operator bool()
, Там нет причин для перегрузки operator!
если вы не хотите, чтобы это делало что-то другое — и если вы думаете, что хотите этого, вам, вероятно, следует подумать еще раз.
Исторически, перегрузка operator bool
откроет дверь для неявного преобразования в любой числовой тип, который может вызвать путаницу, неясности и тонкие ошибки; так что лучше не делать этого. перегрузка operator!
был простой способ разрешить некоторое использование в условных выражениях, не открывая эту дверь, если вы не хотите увязнуть в безопасная идиома. (Ссылка только для исторического интереса; идиома устарел в C ++ 11, благодаря явным операторам преобразования.)
Других решений пока нет …