2016-05-28 11 views
2

Ich habe den folgenden Code ein (sehr aus Gründen der Klarheit vereinfacht):Spezialisieren Elementfunktion einer Templat abgeleiteten Klasse

class Base 
{ 
    virtual int DoStuff(int arg) = 0; 
}; 

template <typename T> 
class Derived : public Base 
{ 
    int DoStuff(int arg) override 
    { 
     // do some stuff 
     return 0; 
    } 
}; 

Dies funktioniert gut. Jetzt möchte ich eine spezielle (vektorisierte) Implementierung von DoStuff implementieren. Und ich brauche die Umsetzung spezifisch sein basierend auf dem Typ T, der hat Abgeleitet, etwa wie folgt:

class Base 
{ 
    virtual int DoStuff(int arg) = 0; 
    virtual int DoStuffVectorized(int arg) = 0; 
}; 

template <typename T> 
class Derived : public Base 
{ 
    int DoStuff(int arg) override 
    { 
     // do some stuff 
     return 0; 
    } 

    int DoStuffVectorized<char>(int arg) override 
    { 
     // do some stuff for T == char 
     return 0; 
    } 

    int DoStuffVectorized<int>(int arg) override 
    { 
     // do some stuff for T == int 
     return 0; 
    } 
}; 

Allerdings bin ich nicht in der Lage, diese Arbeit zu machen.

EDIT: Ich erhalte die folgende Fehlermeldung: Fehler C2143: Syntaxfehler: fehlen; vor '<' auf der Linie int DoStuffVectorized<char>(int arg) override.

Wenn ich ändern es: template<char> int DoStuffVectorized(int arg) override i erhalten: error C2898: ... ': Memberfunktion Vorlagen können nicht virtuell sein

Irgendwelche Tipps, wie so etwas zu erreichen? Der Grund, warum ich es brauche, ist, dass ich einen std :: Vektor habe, der Daten verschiedener Typen speichert (durch Verwendung von Derived <>). Auf diese Weise kann ich denselben einfachen Code verwenden, unabhängig vom Typ, der gespeichert wird, und ich möchte, dass dies auch dann der Fall ist, wenn die spezielle vektorisierte Implementierung von DoStuff verwendet wird, die leider typenspezifisch ist.

+1

Was bedeutet "Ich kann es nicht zum Laufen bringen"? –

+1

"Ich kann diese Arbeit jedoch nicht machen" Warum? Irgendwelche Fehlermeldungen? Was funktioniert nicht? – user463035818

+0

Fehlermeldungen hinzugefügt. Es scheint mir, dass ich in einigen Vererbung/Template-Definition Syntaxfehler verloren gehe? – PeterK

Antwort

3

Sie müssen Vorlage Member-Funktionen außerhalb der Klasse spezialisieren:

#include <iostream> 

class Base 
{ 
    public: 
    virtual int DoStuffVectorized(int arg) = 0; 
}; 

template <typename T> 
class Derived : public Base 
{ 
    public: 
    int DoStuffVectorized(int arg) override; 
}; 

template <> 
int Derived<char>::DoStuffVectorized(int arg) 
{ 
    std::cout << "T == char\n"; 
    return 0; 
} 

template <> 
int Derived<int>::DoStuffVectorized(int arg) 
{ 
    std::cout << "T == int\n"; 
    return 0; 
} 

int main(){ 
    Derived<char> c; 
    Derived<int> i; 
    Base* b[] = { &c, &i }; 
    for(auto* x : b) 
     x->DoStuffVectorized(0); 
    // undefined reference to `Derived<double>::DoStuffVectorized(int)' 
    // Derived<double> d; 
} 

Wenn Sie unbeabsichtigte instantiations bei der Kompilierung erfassen möchten:

#include <type_traits> 

// A std::false_type (useful in a static_assert) 
template <typename T> 
struct static_false : std::false_type 
{}; 

template <typename T> 
int Derived<T>::DoStuffVectorized(int arg) 
{ 
    static_assert(static_false<T>::value, "Neither 'char' or 'int'"); 
    return 0; 
} 
+0

meinst du nicht, wir sollten eine generische generische Überladung für DoStuffVectorized haben sonst wird etwas wie abgeleitet f wird nicht funktionieren – Kapil

+0

Danke, das ist genau das, was ich will! – PeterK

+0

Aber warum Sachen mit std :: false_type verkomplizieren, warum nicht direkt static_assert (false, "Weder 'char' oder 'int'"); – Kapil

2

DoStuffVectorized<char> ist nicht die richtige Syntax, DoStuffVectorized ist nicht Vorlage selbst.

Siehe template specialization:

template <typename T> 
class Derived : public Base 
{ 
    int DoStuff(int arg) override 
    { 
     // do some stuff 
     return 0; 
    } 
    int DoStuffVectorized(int arg) override 
    { 
     // do some stuff (primary template) 
     return 0; 
    } 
}; 

template <> 
int Derived<int>::DoStuffVectorized(int) { 
    // do some stuff for T == char 
    return 0; 
} 

template <> 
int Derived<char>::DoStuffVectorized(int) { 
    // do some stuff for T == char 
    return 0; 
} 
Verwandte Themen