Xcode 4.1 および Visual Studio 2008 で、c++ 標準 ISO/IEC 14882-03 14.6.1/9 のコードをテストします。2 つのコンパイラの出力は、両方とも標準の期待される結果とは異なります。
コードは以下に貼り付けます。
#include <stdio.h>
#include <iostream>
using namespace std;
void f(char);
template <class T > void g(T t)
{
f(1);
f(T(1));
f(t);
}
void f(int);
void h()
{
g(2);
g('a');
}
void f(int)
{
cout << "f int" << endl;
}
void f(char)
{
cout << "f char" << endl;
}
int main() {
h();
return 0;
}
規格の説明として。期待される出力は
f char
f int
f int
f char
f char
f char
Xcode 4.1 でコードをビルドして実行します。出力は以下のとおりです。ビルド設定で、「Compiler for C/C++/Object-C」を Apple LLVM Compiler 2.1、Gcc 4.2、LLVM GCC 4.2 に変更しようとしました。出力は同じです。
f char
f char
f char
f char
f char
f char
Microsoft Visual Studio 2008 でコードをビルドして実行します。出力は次のとおりです。
f int
f int
f int
f int
f char
f char
規格の説明(14.6.1/9)を以下に貼り付けます。
名前が (14.6.2 で定義されているように) テンプレートパラメータに依存しない場合、その名前の宣言 (または宣言のセット) は、名前がテンプレート定義に現れるポイントでスコープ内にあるものとします。名前はその時点で見つかった宣言 (または複数の宣言) にバインドされ、このバインディングはインスタンス化の時点で可視である宣言の影響を受けません。[例:
void f(char);
template<class T> void g(T t)
{
f(1); // f(char)
f(T(1)); // dependent
f(t); // dependent
dd++; // not dependent
}
void f(int);
double dd;
void h()
{
// error: declaration for dd not found
g(2); // will cause one call of f(char) followed // by two calls of f(int)
g(’a’); // will cause three calls of f(char)
—終わりの例]
コードはコンパイラにとって整形式ですが、出力は異なります。このコードを別のプラットフォームに移植することは非常に危険です。
これらのコンパイラが標準に従わない理由を知っている人はいますか?
2011 年 10 月 11 日に編集
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#197によると、標準の例は間違っています。以下のコードを Clang と Gcc でテストします。
#include <stdio.h>
#include <iostream>
using namespace std;
void f(char);
template <class T > void g(T t)
{
f(1);
f(T(1));
f(t);
}
enum E{ e };
void f(E );
void h()
{
g(e);
g('a');
}
void f(E )
{
cout << "f E" << endl;
}
void f(char)
{
cout << "f char" << endl;
}
int main() {
h();
return 0;
}
期待どおりの出力。
f char
f E
f E
f char
f char
f char
ありがとう、
ジェフリー