1

XL C/C++ コンパイラーを V8.0 から V10.1 にアップグレードしていますが、V8.0 でコンパイルされているにもかかわらず、エラーが発生するコードが見つかりました。最小限の例を次に示します。

test.h:

#include <iostream>
#include <string>

template <class T>
void f()
{
  std::cout << TEST << std::endl;
}

test.cpp:

#include <string>
#include "test.h"

namespace
{
  std::string TEST = "test";
}

int main()
{
  f<int>();
  return 0;
}

V10.1 では、次のエラーが発生します。

"test.h", line 7.16: 1540-0274 (S) The name lookup for "TEST" did not find a declaration.
"test.cpp", line 6.15: 1540-1303 (I) "std::string TEST" is not visible.
"test.h", line 5.6: 1540-0700 (I) The previous message was produced while processing "f<int>()".
"test.cpp", line 11.3: 1540-0700 (I) The previous message was produced while processing "main()".

g++ 3.3.2 と 4.3.2 の間にも同様の違いが見つかりました。g ++でも見つけまし#include "test.h"た。名前のない名前空間宣言の後に移動すると、コンパイルエラーがなくなります。

ここで私の質問です。標準はこれについて何と言っていますか? テンプレートがインスタンス化されるとき、そのインスタンスは、テンプレート自体が宣言された時点で宣言されていると見なされますか?それとも、この時点で標準はそれほど明確ではありませんか? n2461.pdf のドラフトを調べてみましたが、決定的なものは何も思いつきませんでした。

4

2 に答える 2

5

これは有効なC++コードではありません。TESTテンプレートパラメータに依存しないTため、解析時にテンプレート定義のコンテキストで検出する必要があります。ただし、そのコンテキストではの宣言がTEST存在しないため、エラーが発生します。

その不正な形式のテンプレートの診断メッセージは、コンパイラーによってインスタンス化されるまで遅らせることができますが、コンパイラーが正常であれば、エラーを早期に診断します。テンプレートがインスタンス化されても、そのコードの診断メッセージを表示しないコンパイラは準拠していません。名前のない名前空間とは何の関係もありません。

さらに、名前空間をそのテンプレートの上に配置しても、そのテンプレートを複数の変換単位で定義して呼び出す場合は、有効なC++プログラムではないことに注意してください。これは、同じテンプレート引数を使用した同じテンプレートの異なるインスタンス化が異なるものを参照するためです(名前のない名前空間の文字列は、別の変換ユニットで定義されるたびに異なるオブジェクトを生成します)。このようなプログラムの動作は定義されていません。

于 2010-03-26T19:23:15.537 に答える
0

このテストは、過去に最も標準に準拠したコンパイラの 1 つであることが示されたComeau オンライン コンパイラに不合格です。その場合、コードが書かれているとおりに間違っていることに賛成しますが、その理由について標準の行を指摘することはできませんでした。ただし、リラックス モードでのコードのコンパイルは成功することに注意してください。

于 2010-03-26T19:15:16.570 に答える