1

テンプレートの特殊化の問題は、テンプレート パラメーターがどこにも使用されていないため、通常の関数のように扱われることです。

そのため、次のコードをヘッダー ファイルに入れると、最初は機能します。

template <typename foo>
void f(foo p)
{
  std::cout << "f one" << std::endl;
}

template <>
void f<int>(int p)
{
  std::cout << "f two" << std::endl;
}

ただし、ヘッダーが 2 つのファイルに含まれていると、これは機能しなくなります。この場合、(VS2010で)得られるエラーは次のとおりです。

templateordering.obj : error LNK2005: "void __cdecl f<int>(int)" (??$f@H@@YAXH@Z) already defined in othertu.obj

これは、他の多くの質問で述べられているように、インラインキーワードを使用することで修正できます。

template <>
inline void f<int>(int p)
{
  std::cout << "f two" << std::endl;
}

今、これは私に2つの質問を提起します:

  1. これを行う他の方法はありますか?ソースファイルに特殊な関数を入れてもうまくいかないようです。おそらく、ヘッダーに何らかの宣言が必要になるためです。
  2. インラインは実際に何をしますか?インラインは使用すべきではないというのは、インターネット全体で一般的な経験則のようです。コンパイラは「いずれにせよ、関数を好きなようにインライン展開する可能性が高い」からです。では、コンパイラが「インライン」として宣言した関数をインライン化しない可能性がある場合、なぜこれが機能するのでしょうか?
4

5 に答える 5

4

これを行う他の方法はありますか?ソースファイルに特殊な関数を入れてもうまくいかないようです。おそらく、ヘッダーに何らかの宣言が必要になるためです。

他の関数と同様に、ヘッダーで特殊化を宣言する必要があります。ヘッダーでインラインで定義するか、(正確に 1 つの) ソース ファイルで定義するかは、あなた次第です。繰り返しますが、他の関数と同様です。inlineあなたが言うように、ヘッダーで定義する場合は宣言する必要があります。

インラインは実際に何をしますか?

通常、1 つの定義規則では、プログラム内の 1 つの翻訳単位で関数を定義する必要があります。実際には、ヘッダーは複数の翻訳単位に含まれることを意図しているため、ヘッダーで関数を定義できないことを意味します。

ただし、ヘッダーで関数を定義したい、または必要とする場合があります。たとえば、一部のコンパイラは、定義を確認できる場合にのみ関数呼び出しをインライン化できます。このinlineキーワードは規則を緩和するため、すべての定義が同一である限り、複数の翻訳単位で関数を定義できます。

于 2012-08-01T12:06:35.200 に答える
3

inline1 つの定義ルールにいくつかの変更を加えることができます。具体的には、宣言された関数 (関数テンプレートの明示的な特殊化を含む) はinline、複数の翻訳単位で定義でき (異なる翻訳単位の定義が同じである場合)、odr-usedである任意の翻訳単位で定義する必要があります。これは、関数テンプレート (特殊化されていない) に適用されるものと同じバージョンのodrルールです。

1 つの翻訳単位で特殊化を定義する (そして他の翻訳単位で使用する前に宣言する) か、定義をヘッダー ファイルに残してinline.

専門分野の宣言は次のようになります。

template<> void f<int>(int p);
于 2012-08-01T12:05:05.773 に答える
1

複数のファイルから同じタイプの関数を使用する場合、関数は各ファイルで定義されます。複数のソース ファイルに含まれるヘッダー ファイルにテンプレート以外の関数定義があるのと同じです。

inline関数を「インライン化」できること、つまり、関数の本体を関数が呼び出された場所に直接配置できることをコンパイラに示すヒントとして関数をマークします。これは、関数が実際には定義されていないことを意味します。コンパイラは、関数をインライン化しないことも決定できます。その場合、inlineキーワードはキーワードのように動作しstaticます。

于 2012-08-01T12:04:30.907 に答える
0

これを行う他の方法はありますか?

template <>
static void f<int>(int p)
{
  std::cout << "f two" << std::endl;
}

またはそれらinlineを持っていますが、実際のインライン化を抑制するために特別なコンパイラフラグ (利用可能な場合) を使用します

インラインは実際に何をしますか?

ベストアンサーはすでに利用可能です:)

于 2012-08-01T12:18:38.010 に答える
0

これを行う他の方法はありますか?ソースファイルに特殊な関数を入れてもうまくいかないようです。おそらく、ヘッダーに何らかの宣言が必要になるためです。

はい、 の宣言と定義を分離するとf<int>、リンカー エラーが解決するはずです。

.h ファイルの宣言の構文:

template <>
void f<int>(int p);
于 2012-08-01T12:07:34.777 に答える