2008-06-06

にわかに信じがたいC++のOverload resolutionのルール

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

3 comments:

  1. boolをintやshortにすると1が呼ばれますね(VC9)
    イマイチよく分かりません・・・

    ReplyDelete
  2. standard conversionsには、
    ポインタから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 ;
    }

    ReplyDelete
  3. もっとこの問題にあった、いい例を思いついた。

    void f(bool) { }
    void g(int) { }

    int main()
    {
    int x ;
    int * ptr = &x ;
    f(ptr) ;//問題ない、ポインタからboolへの変換
    g(ptr) ;//エラー、ポインタから整数値への変換。明示的なreinterpret_castが必要
    }

    ReplyDelete

You can use some HTML elements, such as <b>, <i>, <a>, also, some characters need to be entity referenced such as <, > and & Your comment may need to be confirmed by blog author. Your comment will be published under GFDL 1.3 or later license with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.