2016-06-21 9 views
2

Meine aktuellen Code sieht aus wie folgt: Code hereWie erhält man die innere Template-Klasse zum Typ der äußeren Template-Klasse?

Ich habe eine Vorlage ClassOuter und eine verschachtelte Vorlage ClassInnerBase, wo TypeD von jeder Art von TypeA, TypeB, TypeC und kein anderer sein kann. Desweiteren sollte von ClassInnerBase erben und die virtual const int Method(int id) = 0; implementieren.

template<typename TypeA, typename TypeB, typename TypeC> 
class ClassOuter { 
public: 

    class ClassInnerBase { 
    public: 
     ClassInnerBase(int x) : 
       m_x(x) { 
     } 

     virtual const int Method(int id) = 0; 

    private: 
     int m_x; 
    }; 

    template<typename TypeD> 
    class ClassInnerDerived : public ClassInnerBase { 
    public: 
     ClassInnerDerived<TypeD>(const TypeD &object, int x) : 
       ClassInnerBase(x), m_object(object) { 

     } 

     // Implementation of ClassInnerBase::Method for type float 
     template<> 
     const int ClassInnerDerived<float>::Method(int id){ 
      return GetLookupID(id); 
     } 

     // Implementation of ClassInnerBase::Method for type double 
     template<> 
     const int ClassInnerDerived<double>::Method(int id){ 
      return GetLookupID(id); 
     } 


    private: 
     TypeD m_object; 
    }; 

    void DoSomething(const std::vector<ClassInnerBase> &inner_vec, int id); 

    const int GetLookupID(int id) const{ 
     return lookup[id]; 
    } 

private: 
    int lookup[100]; 
}; 

template<typename TypeA, typename TypeB, typename TypeC> 
void ClassOuter<TypeA, TypeB, TypeC>::DoSomething(const std::vector<ClassInnerBase> &inner_vec, int id){ 
    for(const auto &inner : inner_vec){ 
     inner.Method(id); 
    } 
} 


int main() 
{ 
    std::vector<typename ClassOuter<int, double, float>::ClassInnerBase> class_base_objects; 
    typename ClassOuter<int, double, float>::template ClassInnerDerived<float> class_inner_derived_object(0.2f, 1); 
    class_base_objects.push_back(class_inner_derived_object); 

    typename ClassOuter<int, double, float>::template DoSomething(class_base_objects, 1); 
} 

ich am Ende der Fehler bekommen:

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out 
main.cpp:30:18: error: explicit specialization in non-namespace scope 'class ClassOuter<TypeA, TypeB, TypeC>::ClassInnerDerived<TypeD>' 
     template<> 
       ^

Ich bin hier ganz fest und weiß nicht, wie diese Fehler zu beheben. Gibt es auch irgendwelche Vorschläge/Kommentare/Verbesserungen zur Implementierung?

+0

Sie wäre besser, besser auf [Code Review] (http://codereview.stackexchange.com/) für Verbesserungen an Ihrer Implementierung – Rakete1111

+2

@ Rakete1111 Nein, Code Review ist * nicht * ein Ort für kaputten Code, da es außerhalb des Themas da drüben ist. Er fragte auf der richtigen Seite. – syb0rg

+0

@ syb0rg Ich meinte nur das Verbesserungsbit. Für den eigentlichen Fehler ist OP auf der richtigen Seite – Rakete1111

Antwort

0

Wie Ihr Compiler sagt, können Sie die innere Klasse einer Template-Klasse nicht explizit (vollständig) spezialisieren. Was Sie tun, ist noch schlimmer, wenn Sie versuchen, eine einzelne Methode aus der inneren Klasse zu spezialisieren, was selbst für nicht verschachtelte Template-Klassen unmöglich ist. Sie können den Compiler tricksen, indem Sie zusätzliche Template-Parameter mit dem Standardwert hinzufügen zu deiner inneren Klasse und spezialisiere ganze innere Klasse teilweise. Dadurch können Sie testen, ob der Template-Parameter vom angegebenen Typ ist, indem Sie den sfinae-Mechanismus verwenden (ich habe wie in Ihrem Beispiel getestet, ob der innere Template-Parameter tatsächlich double oder float ist), aber Sie können auch testen, ob es nur einer der äußeren Template-Typen ist auch) zB:

#include <iostream> 
#include <type_traits> 
#include <vector> 

template<typename TypeA, typename TypeB, typename TypeC> 
class ClassOuter { 
public: 

    class ClassInnerBase { 
    public: 
     ClassInnerBase(int x) : 
       m_x(x) { 
     } 

     virtual const int Method(int id) = 0; 

    private: 
     int m_x; 
    }; 

    template<typename TypeD, typename = void> 
    class ClassInnerDerived; 

    template<typename TypeD> 
    class ClassInnerDerived<TypeD, std::enable_if_t<std::is_same<TypeD, float>::value || std::is_same<TypeD, double>::value> >: public ClassInnerBase { 
    public: 
     // Implementation of ClassInnerBase::Method for type float 
     ClassInnerDerived(const TypeD &object, int x) : 
       ClassInnerBase(x), m_object(object) { 
     } 
     const int Method(int id){ 
      return GetLookupID(id); 
     } 
    private: 
     TypeD m_object; 
    }; 

    public: 

    //static void DoSomething(const std::vector<ClassInnerBase> &inner_vec, int id); 

    static const int GetLookupID(int id) { 
     return lookup[id]; 
    } 

private: 
    static int lookup[100]; 
}; 

template<typename TypeA, typename TypeB, typename TypeC> 
int ClassOuter<TypeA, TypeB, TypeC>::lookup[100]; 

/* 
template<typename TypeA, typename TypeB, typename TypeC> 
void ClassOuter<TypeA, TypeB, TypeC>::DoSomething(const std::vector<ClassInnerBase> &inner_vec, int id){ 
    for(const auto &inner : inner_vec){ 
     inner.Method(id); 
    } 
}*/ 


int main() 
{ 
std::vector<typename ClassOuter<int, double, float>::ClassInnerBase *> class_base_objects; 
    //typename ClassOuter<int, double, float>::template ClassInnerDerived<float> class_inner_derived_object(0.2f, 1); 
    class_base_objects.push_back(new ClassOuter<int, double, float>::ClassInnerDerived<float>(0.2f, 1)); //(class_inner_derived_object); 

    //typename ClassOuter<int, double, float>::template DoSomething(class_base_objects, 1); 
} 

Der obige Code wohl tatsächlich nicht tun, was Sie wollen, aber ich denke, ein guter Ausgangspunkt ist ...

Verwandte Themen