5

今日、私の友人の1人が、次のコードが彼のVisualStudio2008で適切にコンパイルされると教えてくれました。

#include <vector>
struct A
{
  static int const const_iterator = 100;
};
int i;
template <typename T>
void PrintAll(const T & obj)
{
  T::const_iterator *i;
}
int main()
{
  std::vector<int> v;
  A a;
  PrintAll(a);
  PrintAll(v);
  return 0;
}

私は通常g++を使用しますが、2番目のPrintAll()呼び出しを渡すことを常に拒否します。私が知っているように、この問題に対して、g++はテンプレートを翻訳する標準的な方法を実行しています。

それで、私の知識は間違っていますか、それともVS2008の拡張ですか?

4

2 に答える 2

8

これはまったく拡張機能ではありません。

VC++ は 2 フェーズの解釈を適切に実装していません。

  1. 定義の時点で、テンプレートを解析し、すべての非依存名を決定します
  2. インスタンス化の時点で、テンプレートが有効なコードを生成することを確認します

VC++ は最初のフェーズを実装していません。これは、準拠していないコードを受け入れるだけでなく、状況によってはまったく異なるコードを生成することを意味するため、不便です。

void foo(int) { std::cout << "int" << std::endl; }

template <class T> void tfoo() { foo(2.0); }

void foo(double) { std::cout << "double" << std::endl; }

int main(int argc, char* argv[])
{
  tfoo<Dummy>();
}

このコードで:

  • これは、テンプレートの定義時点で利用可能な唯一の定義であり、の解決はfooに依存しないためTです。
  • VC++ は、フェーズ 1 を気にしないため、「double」を出力します。

違いに関してはばかげているように思えるかもしれませんが、大規模なプログラムに含まれるインクルードの数を考えると、誰かがテンプレート コードの後に​​オーバーロードを導入するリスクがあります...そして BAM :/

于 2010-06-04T16:28:55.697 に答える
1

この点で「拡張」が正確にVC++をどのように説明するかはわかりませんが、そうです、gccはこの点でより優れた適合性を持っています。

于 2010-06-04T14:18:47.520 に答える