web-dev-qa-db-ja.com

テンプレートメソッドの未定義の参照エラー

これは私をこの1時間半の間怒らせています。私はそれが小さなことであることを知っていますが、何が悪いのかを見つけることができません(もちろん、金曜日の午後は雨であるという事実は役に立ちません)。

ファイルから読み取った構成パラメーターを保持し、プログラムからそれらにアクセスできるようにする次のクラスを定義しました。

_class VAConfig {
    friend std::ostream& operator<<( std::ostream& lhs, const VAConfig& rhs);

private:
    VAConfig();
    static std::string      configFilename;
    static VAConfig*        pConfigInstance;
    static TiXmlDocument*   pXmlDoc;
    std::map<std::string, std::string> valueHash;

public:
    static VAConfig* getInstance();
    static void setConfigFileName( std::string& filename ) { configFilename = filename; }
    virtual ~VAConfig();

    void readParameterSet( std::string parameterGroupName );
    template<typename T> T readParameter( const std::string parameterName );
    template<typename T> T convert( const std::string& value );
};
_

ここで、メソッドconvert()は_VAConfig.cpp_で次のように定義されています

_template <typename T>
T VAConfig::convert( const std::string& value )
{
    T t;
    std::istringstream iss( value, std::istringstream::in );
    iss >> t;
    return t;
}
_

すべて非常に単純です。しかし、私がメインプログラムからテストするとき

_int y = parameters->convert<int>("5");
_

_undefined reference to 'int VAConfig::convert<int>...'_コンパイルエラーが発生します。 readParameter()の同上。

たくさんのテンプレートチュートリアルを見ましたが、これを理解することはできませんでした。何か案は?

44

テンプレートコードの実装は.cppファイルに含めないでください。コンパイラは、テンプレートを生成するために explicit instantiation を使用しない限り、それらを呼び出すコードを確認すると同時にそれらを確認する必要がありますオブジェクトコードですが、それでも.cppは使用するファイルタイプが間違っています)。

実装をヘッダーファイル、またはVAConfig.t.hppなどのファイルに移動し、テンプレート化されたメンバー関数を使用するときはいつでも#include "VAConfig.t.hpp"に移動する必要があります。

70
Seth Johnson

テンプレート化されたメソッド(convertおよびreadParameter)の実装をヘッダーファイルに移動すると、機能するはずです。

コンパイラーは、インスタンス化された時点でテンプレート関数の実装にアクセスできる必要があります。

10
dma

テンプレートメソッドは、メソッドの...テンプレートにすぎません。テンプレートの引数は、メソッドが「インスタンス化」される場所に入力されます。

テンプレートメソッドの宣言でコンテンツであるコンパイラを構築し、「テンプレートコンパイル」ステップでテンプレートメソッドの必要なすべてのインスタンスをコンパイルすることが可能である必要があります。

これは、Microsoftのvcには当てはまりません。けれども、私はそれがunixの場合であることについて同僚のつぶやきを聞いた。

ほとんどのコンパイラは、要求に応じてテンプレートメソッドをインスタンス化します。テンプレートメソッドは、ソースコードで使用されます。メソッドをインスタンス化するために、コンパイラーはテンプレート関数本体を「見る」必要があります。そのため、ほとんどの場合、本文はヘッダーファイルまたは次のいずれかに配置されます。 .h.cppファイル。hファイルの最後の行として含まれます。

5
xtofl