contextually converted to bool

結論から先に言いましょう。
C++0x では、 explicit operator bool を定義すれば、自動的に ! 演算子も使えるようになります:

// getchar の戻り値とかで使えそうな何か
struct hoge {
  hoge() : ch_(-1) {}
  hoge( char ch ) : ch( static_cast<unsigned char>(ch) ) {}

  explicit operator bool() const { return ch_ != -1; }
  char operator*() const { return static_cast<unsigned char>(ch); }
  
 private:
  int ch_;
};

int main()
{
  hoge x('a'), y;
  
  assert( x && *x == 'a' );
  assert( !y ); // operator! は用意されてないけど OK
}


これは、 ! 演算子の対象が "contextually converted to bool" される*1為で、
"contextually converted to bool" というのは、要するに bool に対する明示的な変換である*2から。
というわけで上記コードの !y は問題なくコンパイル通ります。


参考: C++0x explicit bool - Faith and Brave - C++で遊ぼう


ちなみに、このことを調べたのは「あれ? std::unique_ptr に operator! ないけど大丈夫なの?」と思ったのがきっかけ。

C++98/03 で safe bool イディオムを使っていたときは明示的に operator! を定義しないと駄目だった(はず)ですが、
explicit operator bool ではそんな手間をかけなくていいので、楽になったなあと感じた次第。

規格を読み直してみたところ、 C++98/03 であっても、
if の条件部に書けるならば問題なく ! 演算子オペランドとして使えるようです。

*1:詳しくは N3126: 5.3.1 Unary operators [expr.unary.op] の 5 を参照

*2:詳しくは N3126: 4 Standard conversions [conv] の 3 を参照。正確には変換される e に対して bool t(e); という表現が well-formed ならば OK