1. ホーム
  2. c++

[解決済み] なぜテンプレートはヘッダーファイルでしか実装できないのですか?

2022-03-14 09:41:32

質問

引用元 C++標準ライブラリ:チュートリアルとハンドブック :

現時点では、テンプレートを使用する唯一の移植可能な方法は、インライン関数を使用してヘッダーファイルで実装することです。

これはなぜでしょうか?

(明確化:ヘッダーファイルは のみ ポータブルなソリューションです。しかし、最も便利なポータブルソリューションです)。

どのように解決するのですか?

注意:それは ではない この回答の最後にある別の解決策を参照してください。

とにかく、あなたのコードが失敗する理由は、テンプレートをインスタンス化するとき、コンパイラは与えられたテンプレート引数で新しいクラスを作成することです。例えば

template<typename T>
struct Foo
{
    T bar;
    void doSomething(T param) {/* do stuff using T */}
};

// somewhere in a .cpp
Foo<int> f; 

この行を読むと、コンパイラは新しいクラス(仮に FooInt )と同等である。

struct FooInt
{
    int bar;
    void doSomething(int param) {/* do stuff using int */}
}

そのため,コンパイラはメソッドの実装にアクセスし,テンプレートの引数 (この場合は int ). もしこれらの実装がヘッダーになければ、アクセスできないので、コンパイラーはテンプレートのインスタンス化をすることができません。

この問題を解決する一般的な方法は、テンプレートの宣言をヘッダーファイルに記述し、クラスを実装ファイル(例えば.tpp)で実装し、この実装ファイルをヘッダーの末尾にインクルードすることです。

Foo.h

template <typename T>
struct Foo
{
    void doSomething(T param);
};

#include "Foo.tpp"

Foo.tpp

template <typename T>
void Foo<T>::doSomething(T param)
{
    //implementation
}

この方法では、実装は宣言から分離されたままですが、コンパイラからアクセス可能な状態になっています。

代替案

もう一つの解決策は、実装を分離しておき、必要なテンプレートのインスタンスを明示的にすべてインスタンス化することです。

Foo.h

// no implementation
template <typename T> struct Foo { ... };

Foo.cpp

// implementation of Foo's methods

// explicit instantiations
template class Foo<int>;
template class Foo<float>;
// You will only be able to use Foo with int or float

私の説明ではよくわからないという方は この件に関するC++スーパーFAQ .