8

私は静的ライブラリに取り組んでおり、ライブラリには複数のクラステンプレートと関数テンプレートがあります。静的ライブラリ内のテンプレートを使用するには、すべて(宣言/定義)がヘッダーファイルに含まれている必要があることを理解しています。ただし、この特定のケースでは、特殊化のタイプを知っているので、代わりに前方宣言を使用できると思いました。

このトリックはクラステンプレート(およびその関数)でうまく機能し、アプリケーションコードからすべてのライブラリ関数を使用できます。ただし、ライブラリ内に無料の関数テンプレートを導入し、アプリケーションコードから無料のテンプレート関数を使用しようとすると、リンカーエラーが発生します。

エラーLNK2019:未解決の外部シンボル "class TemplatedStaticLib __cdecl HelpingRegistration(int)"(?? $ HelpingRegistration @ H @@ YA?AV?$ TemplatedStaticLib @ H @@ H @ Z)関数_main 1> C:\ src\cppで参照\ vs2008 \ StaticLibExample \ MathFuncsLib \ Debug \ TemplatedStaticLibApp.exe:致命的なエラーLNK1120:1つの未解決の外部 "VS2008を使用しています、ここにコードがあります

//静的ライブラリヘッダーファイル(.h)

#ifndef _TEMPLATED_STATIC_LIB_
#define _TEMPLATED_STATIC_LIB_

#include <iostream>

template<typename T>
class TemplatedStaticLib
{
public:
    TemplatedStaticLib(){};
    ~TemplatedStaticLib(){};

    void print(T t);

};

template<typename T>
TemplatedStaticLib<T> HelpingRegistration(T);


#endif

//静的ライブラリクラスファイル(.cpp)

#include "TemplatedStaticLib.h"

//Specialization
template class TemplatedStaticLib<double>;
template class TemplatedStaticLib<int>;
template class TemplatedStaticLib<std::string>;


template<typename T>
void TemplatedStaticLib<T>::print(T t)
{
    std::cout << "Templated Print "  << typeid(t).name() << std::endl;
}

void HelpingRegistration(void)
{
}

//Specialization of free function
template<> TemplatedStaticLib<int> HelpingRegistration<int>(int);
template<> TemplatedStaticLib<double> HelpingRegistration<double>(double);
template<> TemplatedStaticLib<std::string> HelpingRegistration<std::string>(std::string);

template<typename T>
TemplatedStaticLib<T> HelpingRegistration(T t)
{
       std::cout << "Function Templated Print "  << typeid(t).name() << std::endl;
       return t;
}

//アプリケーションコード

#include "TemplatedStaticLib.h"

int main(int argc, char* argv[])
{
    int anInt = 99;
    TemplatedStaticLib<int> test; 
    test.print(anInt);//works

    double aDouble = 3.9;
    TemplatedStaticLib<double> double_test; 
    double_test.print(aDouble); //works

    std::string aString = "James";

    TemplatedStaticLib<std::string> string_test; 
    string_test.print(aString);//works

    //The following lines gives linker error
    HelpingRegistration(anInt);
    HelpingRegistration(aDouble);
    HelpingRegistration(aString);


    return 0;
}

なぜ違うのか、どうすれば修正できるのかわかりません。どんな助けでも大歓迎です。

4

1 に答える 1

13

これらは前方宣言ではなくクラステンプレートの明示的なインスタンス化であることに注意してください。これ.cppにより、他の翻訳ユニットでこれらのテンプレートのインスタンス化のみを使用する限り、定義をファイルに入れて、リンカーによる未解決の参照エラーを取得できなくなります。

一方、これらは:

template<> TemplatedStaticLib<int> HelpingRegistration<int>(int);
template<> TemplatedStaticLib<double> HelpingRegistration<double>(double);
template<> TemplatedStaticLib<std::string> HelpingRegistration<std::string>(std::string);

関数テンプレートの明示的な特殊化の宣言です。代わりに、明示的なインスタンス化を提供することを意図している可能性があります。そのための構文は次のとおりです。

template TemplatedStaticLib<int> HelpingRegistration<>(int);
template TemplatedStaticLib<double> HelpingRegistration<>(double);
template TemplatedStaticLib<std::string> HelpingRegistration<>(std::string);

これを修正すると、コンパイラが実際に関数テンプレートをインスタンス化することがわかります。また、(または)をタイプ(resp。)のオブジェクトにHelpingRegistration<>()変換しようとしているため、その間にエラーが発生します。 。または)、変換が提供されていない(または少なくとも投稿したコードに表示されていない):intdoublestringTemplatedStaticLib<int>TemplatedStaticLib<double>TemplatedStaticLib<string>

template<typename T>
TemplatedStaticLib<T> HelpingRegistration(T t)
{
    std::cout << "Function Templated Print "  << typeid(t).name() << std::endl;
    return t; // CANNOT BE CONVERTED!
}

このエラーを修正すると(たとえば、を実行してreturn TemplateStaticLib<T>();)、プログラムがコンパイルおよびリンクされます。

于 2013-02-26T01:24:52.887 に答える