2

次のコードは、コンパイル/リンカー エラー/警告を生成しません。

// A.h
#include<iostream>
struct A
{
  template<typename T>
  static void foo (T t)
  {
    std::cout << "A::foo(T)\n";
  }
};
void other ();

// main.cpp
#include"A.h"
int main ()
{
  A::foo(4.7);
  other();
}

// other.cpp
#include"A.h"
template<>
void A::foo (double d)
{
  cout << "A::foo(double)\n";
}

int other ()
{
  A::foo(4.7);
}

出力は驚くべきことに次のとおりです。

A::foo(T)
A::foo(double)

A::foo(double)の場合、コンパイラが正しいものを取得できないのはなぜmain.cppですか?

A.h以下のような宣言がある場合、期待どおりに問題がないことに同意します。

template<> void A::foo (double);

しかし、リンク時にコンパイラが特殊化されたバージョンを持っているため、それは問題ではありません。

また、同じ関数の 2 つの異なるバージョンが未定義の動作ですか?

4

3 に答える 3

6

すべての明示的な特殊化宣言は、テンプレートのインスタンス化時に可視でなければなりません。の明示的な特殊化宣言は一方の翻訳単位でA::foo<double>は表示されますが、もう一方の翻訳単位では表示されないため、プログラムの形式が正しくありません。

(実際には、コンパイラはプライマリ テンプレートを でインスタンス化しmain.cpp、明示的に特殊化されたテンプレートを でインスタンス化しother.cppます。いずれにせよ、それでも ODR 違反になります。)

于 2012-10-26T14:25:39.753 に答える
0

main.cppの場合、コンパイラが正しいA :: foo(double)を取得できないのはなぜですか?

問題は、ヘッダーで使用可能な宣言がない別のコンパイルモデルでは、コンパイラは、後でリンクされる変換ユニットに特殊化が存在するかどうか、またはテンプレートをインスタンス化する必要があるかどうかをおそらく認識しないことです。言語での決定は、宣言がないということは、テンプレートを手動で特殊化する必要がないことを意味するため、コンパイラーは今すぐテンプレートを生成する必要があるということです。

同じ関数の2つの異なるバージョンが未定義の動作をしていますか?

はい、そうです。スペシャライゼーションの1つが自動的に生成されたかどうかに関係なく、1つの定義ルールに違反しているため、未定義の動作であるという事実があります(同じシンボルの定義が複数あります)。

于 2012-10-26T15:17:59.737 に答える
0

main.cpp内のコードを見ることができませんother.cpp。テンプレートの特殊化はファイル スコープです。

于 2012-10-26T14:26:58.433 に答える