2016-06-24 11 views
3

C++でネストされたビルダークラスを開発しようとしていますが、この「不完全な型の無効な使用」クラスNpc :: Builder < 'T>」エラーが続いています。私はたくさんの検索をしましたが、私は答えを見つけることができませんでした。誰でも助けてくれますか?ビルダーパターン、テンプレート、ネストされたクラス

ここに私のコードは次のとおりです。

Npc.h 
class Npc{ 
    ... 
    template<class T, class enable_if<is_base_of<Npc, T>::value>::type* = nullptr> 
    class Builder{ 

    private: 
     T* instance; 

    public: 
     Npc::Builder<T>* create(); 
     Npc::Builder<T>* name(string name); 
     Npc::Builder<T>* charClass(string charClass); 
     Npc::Builder<T>* hp(int hp); 
     Npc::Builder<T>* mana(int mana); 
     Npc::Builder<T>* attackPower(int attackPower); 
     Npc::Builder<T>* magicPower(int magicPower); 
     Npc::Builder<T>* defense(int defense); 
     Npc::Builder<T>* magicDefense(int magicDefense); 
     T* build(); 
    }; 
}; 


Npc.cpp 
... 
template<class T, class enable_if<is_base_of<Npc, T>::value>::type* = nullptr> 
Npc::Builder<T>* Npc::Builder<T>::create() { 
    ... 
} 

main.cpp 
... 
Npc::Builder<Warrior>* builder = new Npc::Builder<Warrior>(); 
... 

ありがとう!

+0

を、私はそれが本当だとは思いません問題。実際、ヘッダーにテンプレートを実装する必要がありますが、これはリンカーエラーのみにつながります。ここでOPにはコンパイル時エラーがあります。これは 'typename'がないことから起こりそうです。 – vsoftco

+1

npcの実装を.hファイルに移動します。すべてのテンプレートコードは、使用されているソースからアクセス可能でなければなりません。たとえば、テンプレート化されたクラスを持っている場合は、外部コードで使用する必要がある場合はヘッダのみのクラスにする必要があります – fnc12

答えて

1

コードに構文上の誤りがあります。最も重要なのは、missing a typename (as you have a dependent type)であり、この場合は2番目のテンプレートパラメータが非タイプであることがデフォルト値のnullptrであるためです。 typenameが欠落し、デフォルトのparamを持つことができません。

// non-type param 
template<class T, typename std::enable_if<std::is_base_of<Npc, T>::value>::type* = nullptr> 
class Builder { ... }; 

か、それタイプ

// type param 
template<class T, class = typename std::enable_if<std::is_base_of<Npc, T>::value>::type> 
class Builder { ... }; 

次に、ライン

template<class T, enable_if<is_base_of<Npc, T>::value>::type* = nullptr> 
Npc::Builder<T>* Npc::Builder<T>::create() { 
    ... 
} 

が間違っている作りを使用してください。また、コンパイラは、テンプレート・メンバー関数を部分的に専門化していると考えていますが、これは許可されていません。何が必要のようなものです:

template<class T, typename std::enable_if<std::is_base_of<Npc, T>::value>::type* U> 
Npc::Builder<T, U>* 
Npc::Builder<T, U>::create() { 
    return nullptr; 
} 

以下のコード上記の問題をすべて修正し、完全な作業例を示します。

#include <iostream> 
#include <type_traits> 

class Npc { 
public: 
    template<class T, 
      typename std::enable_if<std::is_base_of<Npc, T>::value>::type* U = nullptr> 
    class Builder { 
    private: 
     T* instance;  
    public: 
     Builder* create(); // no need for Noc::Builder<T>, due to template name injection 
     Builder* name(std::string name); 
     Builder* charClass(std::string charClass); 
     Builder* hp(int hp); 
     Builder* mana(int mana); 
     Builder* attackPower(int attackPower); 
     Builder* magicPower(int magicPower); 
     Builder* defense(int defense); 
     Builder* magicDefense(int magicDefense); 
     T* build(); 
    }; 
}; 

struct Warrior: Npc{}; 

template<class T, typename std::enable_if<std::is_base_of<Npc, T>::value>::type* U> 
Npc::Builder<T, U>* 
Npc::Builder<T, U>::create() { 
    return nullptr; 
} 

int main() 
{ 
    Npc::Builder<Warrior>* builder = new Npc::Builder<Warrior>(); 
    delete builder; 
} 

Live on Coliru

+0

create()メソッドの定義を追加すると、エラーが発生します。 [こちら](http://coliru.stacked-crooked.com/a/efa4a0463fc7475b) – lcleite17

+0

@ lcleite17編集を参照して、私は何が起こっているのか把握しました。私が投稿した解決策はうまくいくはずです.gcc/clangを使って私のためにコンパイルします。 – vsoftco

+0

ありがとう!それは今働きます! – lcleite17

関連する問題