2

関数、ADT、およびクラスの C および C++ での非常に一般的なコーディング パターンは次のとおりです。

  • (クラスの関数の) 宣言を含むヘッダー .h ファイル。
  • 実際のコードを含む実装 .cpp ファイル。

これらは個別のオブジェクト (共有または非共有) にコンパイルされます。宣言されたエンティティ ('foo' と呼びましょう) を使用する他のコードには、foo.h ファイルが含まれ、個別にコンパイルされてから foo.o に対してリンクされます。

ただし、テンプレート化された foo では、これは不可能です。必須のインスタンス化の型を指定しないと、foo.o は役に立ちません。誰もが行っているように見えるのは、実装コード (通常は foo.cpp) をユーザー コードと同じ翻訳単位に含めることです。

foo.cpp を含める必要のないメカニズムを使用して、これを回避できるようにしたいと思います。理想的には、これはうまくいくはずです:

main.cpp:

#include "foo.h"
int main() {
    foo<int>();
}

foo.h:

template<typename T> void foo();

foo.cpp:

template<typename T> void foo() {
    // implementation here
}

そのためには、実装コードを含める必要がなく、ヘッダーだけを含める必要があるように、ソース ファイルとヘッダー ファイルだけでなく、おそらくビルド メカニズムを含む、ある種の巧妙なイディオムが必要だと思います。おそらく、次のような行を持つ自動生成ヘッダーを含む、実装ファイルの行に沿って何かを考えていました

template foo<int>();

これは、オブジェクト ファイルが欠落しているインスタンス (つまり、2 つのコンパイル パス) の解析、またはソースの解析 (コンパイラの微調整? 補助出力の有効化?) です。そのようなイディオムを提案できますか?または、私が検討していない別の選択肢はありますか?

注:もちろん、要点は、foo モジュール ( foo.h, foo.cpp) のコードは、どのインスタンス化が必要かを「認識」していないということです。たとえば、またはmain()を使用するかどうかを認識していません。foo<int>()foo<unsigned char>()

4

2 に答える 2

2

それは明示的なインスタンス化です。

template foo<int>();

fooに実装するようにコンパイラに指示しintます。ファイルintに実装を書くようなものです。.cppこれは、将来使用される型がわかっている場合に役立ちます。foo<int>多くの翻訳単位で使用している場合、プロジェクトの合計コンパイル時間を短縮できます。例えば:

ファイルFooBar.h:

template <typename T>
class Bar
{
public:
    T data;
    void func();
};

template<typename T> void foo();

ファイルFooBar.cpp:

template <typename T>
void Bar<T>::func()
{
}

template <typename T>
void foo() {
}

// explicit instantiation

template class Bar<int>;
template class Bar<std::string>;
template foo<int>();
template foo<float>();

主な問題は、テンプレート化されたものはインスタンス化された型だけで使用する必要があることですfooBarたとえば、fooは と に限定されintfloatは とBarに限定されintますstd::string

于 2013-11-05T16:29:24.683 に答える