2011-10-03 3 views
14

Xcode 4.1およびVisual Studio 2008のC++標準ISO/IEC 14882-03 14.6.1/9のコードをテストします。 2つのコンパイラは両方とも、標準の期待される結果とは異なります。クラステンプレートの名前解決の実際の結果は、C++ 03標準とは異なります

コードは以下に貼り付けられています。

#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 

おかげで、

ジェフリー

+2

+1の最初の質問 –

+0

興味深いことに、Clang 2.9はgccと同じ問題があるようです。 –

答えて

3

最初の例で説明したように、これはGCCとClangの両方が実装しているが、MSVCは実装していない2フェーズの名前ルックアップのインスタンスです。この場合、GCCとClangの両方が正しいです.C++ core defect report #197で指摘されているように、実際には間違った標準です。 C++ 11標準には、別の例が含まれています。

MSVC(決して2フェーズの名前のルックアップを実装していない)または(最近まで2フェーズの名前のルックアップを一様に実装していない)GCCからコードをClangに移植するときに表示されるのは、このコードの1つです。

2

私は、これは不正な動作であることをあなたに同意することを除いて、あなたに伝えるためにかわかりません。

おそらく起こっていることは、MSVCの場合、コンパイラは、後で定義された関数の知識で終わるコストで余分なパスを最適化していることです。 -template呼び出し。私は告白する必要がありますが、結果はGCC/LLVMがどのように結果に結びつくのかを知ることはできません。

私はhttp://bugreport.apple.com/http://connect.microsoft.com/のバグとして報告し、彼らの言うことを参照してくださいね。

+0

ありがとう、Mahmoud。コメントがあれば更新してください。 – Jeffrey

+1

@ジェフリー:彼はあなたがバグを提出することを提案していたと思います。 :) –

+0

g ++ 4.6.1はXcode(これは比較的古いg ++ 4.2を使用しています)と同じ動作を示しますので、http://gcc.gnu.org/bugzilla/にもバグレポートを提出してください。 – zwol

5

Visual Studioではtwo-phase lookupが実装されていません。テンプレートをインスタンス化するときにのみ、実際の名前が検索されます。

マイクロソフトでは、2フェーズルックアップをサポートすることに関心がないということは、今のところほとんど決定しています。

+0

MSVC失われた原因ですが、gccとClangが間違ってしまうのは驚きです。 –

関連する問題