条件式のタイプ

2389 ワード

に質問
次のプログラムの出力は何ですか?
#include 

using namespace std;

void f(long);
void f(const char*);

int main()
{
    f(1?0:1);

    return 0;
}

void f(long)
{
    cout << "long" << endl;
}

void f(const char*)
{
    cout << "const char*" << endl;
}

残念ながら、g++ではコンパイルは通過しませんでした:
$> g++ conditional_exp.cpp conditional_exp.cpp: In function ‘int main()’: conditional_exp.cpp:10:エラー:リロードを呼び出す「f(int)」に曖昧なconditional_exp.cpp:5:注記:代替:void f(long int)conditional_exp.cpp:6:注記:void f(const char*)
条件式(1?0:1)のタイプは何ですか?
cout << typeid(1?0:1).name() << endl;

以上の出力文字iは、式のタイプを表すintである
f(1)を呼び出すと、一番上のプログラムのコンパイルは正常で、出力はlongです.
f(0)を呼び出すと,最上位のプログラムも同様のコンパイルエラーを報告する,すなわち,コンパイラから見れば(1?0:1)は0と区別されない.
字面値0のタイプはintであり、パラメータがintの関数がなく、暗黙的なタイプ変換が必要であり、0はlongに変換してもよいし、空のポインタとしてconst char*に変換してもよいし、二義性を生じ、コンパイルエラーを発生する.
次のように呼び出します.
	const char* p = NULL;
	f(p==NULL?0:1);
eclipseは引き続き二義性を提示しますが、コンパイルはエラーも警告もなく、プログラム出力はlongです(なぜ1?0:1の結果はコンパイルエラーですが、ここでコンパイルは正常ですか?)
コンパイル時と実行時の結果がこのように異なるのは、実行するルールが少し異なるのではないでしょうか.
結果から見ると、コンパイルはより厳格な検査を実行し、エラーを報告するのはcoderに注意することであり、この場所ではエラーが発生する可能性が高い.実行時には、intを暗黙的にlongに変換し、正しい関数を呼び出すルールに従います.
以下に、いくつかの試みのまとめを示します.
	f(1?0:1);              //compile error
	f(0);                  //compile error
	f(1?2:1);              //call f(long)

	const char* p = NULL;
	f(p==NULL?0:1);        //eclipse complain, compile succeed, call f(long)

	f(NULL);               //compile error
	f(0L);                 //call f(long)
	f((const char*)0);     //call f(const char*)

関数の再ロードを1つ追加すると、次のようになります.
void f(int)
{
	cout << "int" << endl;
}

compile errorとeclipse complainはありません.タイプはintの0で、正確な関数プロトタイプが見つかりました.タイプ変換は必要ありません.
	f(1?0:1);              //call f(int)
	f(0);                  //call f(int)
	f(1?2:1);              //call f(int)

	const char* p = NULL;
	f(p==NULL?0:1);        //call f(int)

	f(NULL);               //call f(long)
	f(0L);                 //call f(long)
	f((const char*)0);     //call f(const char*)

推奨
呼び出し時に、0にL接尾辞を付けます.次のようにします.
f(1?0L:1);

より良い方法は、intのパラメータを追加する関数の再ロードです.
void f(int i)
{
	f((long)i);
}