4

私の DLL には、クラス テンプレートと、そのテンプレートのインスタンス化から派生した 2 番目のクラスがあります。両方のクラスがエクスポートされ、他の DLL で使用できるようになります。コンパイラは Visual Studio 2013 です。テンプレート コードを正確に 1 つの翻訳単位でインスタンス化する必要があるため、明示的なインスタンス化を採用しています。

DLL1 内のコードは、次のように配布されます。基本クラス テンプレート:

// In BaseTemplate.h:
#pragma once

template<typename T> 
class BaseTemplate
{
public:
    T foo(T t);
};

// declare explicit instantiation
extern template class BaseTemplate < int >;    

// In BaseTemplate.cpp:
#include "BaseTemplate.h"

// template method definition
template<class T>
T BaseTemplate<T>::foo(T t)
{
    return t;
}

// explicit instantiation and export
template class __declspec(dllexport) BaseTemplate < int >;    

派生クラス:

// In Derived.h:
#pragma once
#include "BaseTemplate.h"

#ifdef DLL1_EXPORTS // this is predefined in DLL1
#define DLL1_API __declspec(dllexport)
#else
#define DLL1_API __declspec(dllimport)
#endif

class DLL1_API Derived : public BaseTemplate < int >
{
public:
    void bar();
};

理論的には、externステートメントは、明示的なインスタンス化が実行される BaseTemplate.cpp を除くすべての翻訳単位でのインスタンス化を防止するというものでした。ただし、次の警告が表示されます (プロジェクトではエラーとして扱われるため、ビルドが中断されます)。

1> basetemplate.h(19): warning C4661: 'int BaseTemplate<int>::foo(T)' :
1> no suitable definition provided for explicit template instantiation request
1> with
1> [
1>    T=int
1> ]
1> basetemplate.h(15) : see declaration of 'BaseTemplate<int>::foo'

externステートメントを無視して、派生クラスのエクスポートがインスタンス化をトリガーするようです。派生クラスからエクスポート マクロを削除すると、DLL1 は警告なしでコンパイルされます (ただし、他の DLL は明らかにリンクに失敗します)。継承するのではなく、Derived クラスで BaseTemplate 型のメンバーを集約すると、(エクスポートを使用しても) 同様に機能します。

明示的なテンプレートのインスタンス化とエクスポートされた派生クラスを Visual Studio で組み合わせるにはどうすればよいですか?

4

1 に答える 1