1

で宣言され、で定義された非型テンプレート関数f(int)(パラメータ) があるとします。でさらにの特殊化を 1 つ追加し、 と のテンプレート関数を明示的にインスタンス化します。<int dim>template.htemplate.cpptemplate.cppdim = 2dim = 1dim = 2

ファイルは正常にコンパイルされますが、リンク プロセス中にエラーが発生します。

Undefined symbols for architecture x86_64:
  "void f<2>(int)", referenced from:
      _main in main-2AW7ED.o
ld: symbol(s) not found for architecture x86_64

inlineただし、テンプレートの特殊化 (下のマークを参照) からキーワードを削除すると、すべてが期待どおりに機能します。だからここに私の質問があります:

inlineベーステンプレートでは機能するのに、他のすべてがコンパイルされて正常に機能するのに、特殊なテンプレートでは機能しないのはなぜですか?

main.cpp

#include <iostream>
#include "template.h"

using namespace std;

int main(int, char** )
{
  f<1>(456); 
  f<2>(789);
}

template.h

template <int dim> void f(int src);

テンプレート.cpp

#include <iostream>
#include "template.h"

using namespace std;

template <int dim> inline
void f(int src)
{
  cout << "src = " << src << endl;
  cout << "dim (template) = " << dim << endl;
}

template <> inline // <== if I remove this "inline", everything works as expected
void f<2>(int src)
{
  cout << "src = " << src << endl;
  cout << "dim (fixed) = " << 2 << endl;
}

template void f<1>(int);
template void f<2>(int);

clang++ -o tmpl template.cpp main.cppPS:コンパイルするコマンドで g++ と clang++ を使用しました。

4

1 に答える 1

3

関数が宣言されている場合、関数へのポインターが要求されない限りinline、コンパイラーは非インラインバージョンを生成する必要はありません。または、呼び出しサイトでインライン化しない方がよいと判断した場合を除きます(コンパイラーは常にインライン化する必要はありません宣言した場合inline)。

関数をインライン化するには、コンパイラは呼び出しサイトをコンパイルするときに関数の定義を確認する必要があります。しかし、あなたはで関数を定義し、.cpp別のからそれを呼び出そうとしています.cpp。そのため、コンパイラーは定義を認識せ、非インラインバージョンを呼び出そうとします。ただし、コンパイラに関数をインライン化するように指示し、非インラインバージョンが必要な場所での使用が見当たらないため、生成されませんでした。そのため、生成されませんでした。を宣言しない場合inline、デフォルトよりもextern非インラインバージョンが常に生成されます。そして、生成したい明示的なインスタンスを宣言したので、それらは生成されます。

コンパイラがインラインである必要がないのと同じように、外部バージョンを生成する必要もありません。ある場合にはコンパイラが非インラインインスタンスを生成し、他の場合には生成しないランダムな違いがあるのではないかと思います。いずれの場合も、インラインで宣言する場合は、実際に1つのソースからのみ使用している場合を除き、ヘッダーで定義する必要があります(たとえば、プライベートメソッドは、その1つでのみ使用しているため、インラインで定義して実装で定義できる場合があります)。ファイル)。

于 2013-02-07T10:08:48.243 に答える