2016-06-24 16 views
3

Ich versuche, eine verschachtelte Builder-Klasse in C++ zu entwickeln, aber ich bekomme diese "ungültige Verwendung von unvollständigen Typ 'Klasse Npc :: Builder <' T>" Fehler. Ich habe viel gesucht und konnte keine Antwort finden. Kann mir bitte jemand helfen?Builder-Muster, Vorlagen und verschachtelte Klasse

Hier ist mein Code:

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>(); 
... 

Dank!

+0

Ich glaube nicht, das ist die wirkliche Problem. In der Tat muss man die Vorlage in Kopfzeilen implementieren, dies führt jedoch nur zu Linker-Fehlern. Hier hat OP Kompilierzeitfehler, die höchstwahrscheinlich auf das Fehlen von typename zurückzuführen sind. – vsoftco

+1

Verschieben Sie Ihre NPC-Implementierung in die .h-Datei. Der gesamte Vorlagencode muss von der Quelle, an der er verwendet wird, zugänglich sein. Zum Beispiel, wenn Sie eine Template-Klasse haben - es muss eine Header-Only-Klasse sein, wenn Sie es in äußeren Code verwenden müssen – fnc12

Antwort

1

Es gibt einige syntaktische Fehler in Ihrem Code. Am wichtigsten ist, dass Sie missing a typename (as you have a dependent type) sind, und auch der zweite Vorlagenparameter ist in diesem Fall ein Nicht-Typ, da Sie standardmäßig auf nullptr eingestellt sind. Verwenden Sie

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

oder es eine Art machen

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

nächstes die Linie

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

ist falsch: fehlende typename kann nicht Standard param haben. in der Definition, und auch der Compiler glaubt, dass Sie die Template-Member-Funktion, die nicht erlaubt ist, teilweise spezialisiert. Was Sie brauchen, ist so etwas wie:

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; 
} 

Der Code unten ein komplettes Arbeitsbeispiel zeigt, dass alle Probleme behebt oben erwähnt:

#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

Ich bekomme immer noch den Fehler, wenn ich die Definition der create() -Methode hinzufügen. Wie [this] (http://coliru.stacked-crooked.com/a/efa4a0463fc7475b) – lcleite17

+0

@ lcleide17 Siehe die Änderung, ich fand heraus, was los war. Die Lösung, die ich gepostet habe, sollte funktionieren, es kompiliert für mich mit gcc/clang. – vsoftco

+0

vielen dank! Es funktioniert jetzt! – lcleite17

Verwandte Themen