スマートポインタのようなクラスを作成する場合、if文でヌルポインタかどうか判定できるようにするために
operator boolをオーバーロードします。
template <class T> class smart_ptr { T* p_; public: operator bool() const { return p_ != 0; } }; smart_ptr<int> p; // OK if (p) { // ポインタは有効 } else { // ポインタは無効 }
しかし、この方法では以下のような意味のないコードもコンパイルが通ってしまいます。
float f = p; int x = p + 1; cout << p << endl;
C++03には、この問題を解決するために"conversion to unspecified bool"というイディオムがあります。
これを使用すると、if文での使用を許可し、上記のような意味のないコードはコンパイルエラーにすることができます。
(boost::shared_ptr等で使用されています)
template <class T> class smart_ptr { T* p_; public: smart_ptr(T* p = 0) : p_(p) {} typedef smart_ptr<T> this_type; typedef T* (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const { return p_ ? &this_type::get : 0; } T* get() { return p_; } };
C++0xでは、explicit conversionを使用してexplicit operator boolをオーバーロードすることで、
"conversion to unspecified bool"イディオムを使用しなくてもよくなります。
template <class T> class smart_ptr { T* p_; public: explicit operator bool() const { return p_; } }; smart_ptr<int> p; // OK if (p) { // ポインタは有効 } else { // ポインタは無効 } float f = p; // エラー! int x = p + 1; // エラー! cout << p << endl; // エラー!
ただし、このままではsmart_ptrと0リテラルとの比較がコンパイルエラーになってしまいます。
if (p == 0) { // エラー! }
これを回避するため、C++0xのスマートポインタ(shared_ptr, unique_pr)には、nullptrを受け取るコンストラクタが用意されます。
shared_ptr(nullptr_t) : shared_ptr() {}
unique_ptr(nullptr_t) : unique_ptr() {}
N2435 Explicit bool for Smart Pointers