web-dev-qa-db-ja.com

テンプレートクラスの前方宣言時の「未定義テンプレートの暗黙的なインスタンス化」

テンプレートクラスを前方宣言する必要のあるコードがあります(または、少なくとも、前方宣言を行うと物事がずっと簡単になります...)。私が抱えている問題の簡略版を書いたので、ここに表示できます。

template<bool>
class MyTemplateClass;

int main( int argc, char* argv[] )
{
    MyTemplateClass<false> myTemp;  // error here
    myTemp.GetTheValue();
    return 0;
}

template<bool bShouldMult>
class MyTemplateClass
{
    int m_myint;
    float m_myfloat;

public:
    MyTemplateClass() : m_myint(5), m_myfloat(3.0f) {}
    float GetTheValue()
    {
        return m_myint * (bShouldMult ? m_myfloat : 1.0f);
    }   

};

コメント行で私が得ているエラーは次のとおりです:

Error - implicit instantiation of undefined template 'MyTemplateClass<false>'

MyTemplateClassの前方宣言には、他にどのような詳細を含める必要がありますか?エラーは次の行から発生するものではないため、メソッドが未定義であるという事実によるものではないと考えています。私が使用しているコンパイラはLLVM/CLangで、Macでコンパイルしています。

28
benwad

テンプレートの有無にかかわらず、任意の型の変数を宣言するには、その型の定義全体が利用可能でなければなりません。テンプレートを前方宣言してから、定義されているように使用を開始することはできません。その時点でできることは、次のように、テンプレートに基づいた型のオブジェクトへのポインターを宣言することだけです。

MyTemplateClass<false> *myTempPtr;  // No error here

残念ながら(予想外ではありませんが)、これによりエラーが次の行に移動します。そのポインターを初期化する問題は残ります:new MyTemplateClass<false>を呼び出そうとすると、エラーが表示されます。

テンプレートの定義をその使用場所の前に移動するには、コードを再配置する必要があります。これは多少面倒ですが、それを回避する方法はありません。コンパイラは、テンプレートのインスタンス化とそのメソッドの呼び出しを開始する時点で定義全体を保持する必要があります。

24
dasblinkenlight

#include何かを忘れましたか?

忘れてしまった

#include <array>

std::arrayを使用する場合

:^)

68
kmiklas

あなたが何かを前方宣言して、それをあなたのスタックでインスタンス化することはできないことは私の理解からです(テンプレートかどうか)。

また、テンプレートクラスの前方定義に対する非常に幅広いサポートがあるとは思わない

0
Arthur