C++標準ライブラリのI/Oストリームにある暗黙のユーザ定義変換(user-defined conversion)のせいで、プログラマが意図しない動作を引き起こすケースがある。
#include <iostream> int main() { std::cout << std::cin; // ?? }
上記コードは正常にコンパイル可能。gcc 4.6.3でコンパイルしたときの実行結果の例。
$ g++ -W -Wall -Wextra -pedantic source.cpp $ ./a.out 0x6c504048
ここではbasic_istream<char>
型のcin
オブジェクトに対して、その公開基底クラスbasic_ios<char>
のユーザ定義変換関数operator void*() const
が暗黙的に呼び出されている。C++03 27.4.4.3/p1より引用。
operator void*() const;
Returns: Iffail()
then a null pointer; otherwise some non-null pointer to indicate success.
basic_ostream<char>
型のcout
オブジェクトに対して、同クラスのメンバ関数operator<<(const void* p)
が呼び出され、最終的にポインタ値として出力される。結局のところ下記コードと等価。
std::cout << static_cast<void*>( static_cast<std::ios&>( std::cin ) );
C++11において前述のユーザ定義変換関数(basic_ios<〜>
→void*
)は削除され、代わりにユーザ定義変換関数explicit operator bool() const
が追加された。N3337 27.5.5.4/p1より引用。(また、C.2.15で互換性について言及されている。)
explicit operator bool() const;
Returns:!fail()
.
注意:ユーザ定義変換でのexplicit指定が可能なのはC++11から。C++98/03ではill-formed。
関連URL: