class string {
public:
string(const char*);
} ;
void f(string, string, bool = false) ; // 1
void f(string, bool = false) ; // 2
void g()
{
f(“Hello”, “Goodbye”) ;// 2が呼ばれる
}
なぜか。まずオーバーロードの解決をするために、一つ目の引数を見る。これはどちらの関数も、string型を取る。string型はコンストラクタにconst char *型を取るので、コンパイラはstring型に変換できる。二つ目の引数はどうか。関数1はstring型を引数に取るが、関数2はboolである。人間的に考えると、関数1を呼んで欲しい。しかし、規格では、関数2が呼ばれるのが正しい挙動だ。なぜかというと、コンストラクタを使って変換するより、ポインタをboolに変換するほうが、規格上、より高い候補になるからだ。そんなわけで、コンパイラは、関数2を、正しく、呼ぶことになる。。
via Some C++ Gotchas
boolをintやshortにすると1が呼ばれますね(VC9)
ReplyDeleteイマイチよく分かりません・・・
standard conversionsには、
ReplyDeleteポインタからboolに変換するということは規定されていますが、ポインタから整数値に変換するという規格はありません。
int * f(void) { static int x ; return &x ; }
int main()
{
bool b = f() ;
//オッケー
if ( b == true )
std::cout << "NULLじゃないよ!" << std::endl ;
//エラー、reinterpret_castが必要
unsigned int i = f() ;
if ( i == 0xdeadbeef)
std::cout << "ポインタの値は0xdeadbeef だよ!" << std::endl ;
}
もっとこの問題にあった、いい例を思いついた。
ReplyDeletevoid f(bool) { }
void g(int) { }
int main()
{
int x ;
int * ptr = &x ;
f(ptr) ;//問題ない、ポインタからboolへの変換
g(ptr) ;//エラー、ポインタから整数値への変換。明示的なreinterpret_castが必要
}