5 Stimmen

Vorlage, die die Schnittstelle

Ist es möglich, eine Vorlage zu erstellen, die Typen akzeptiert, die eine bestimmte Schnittstelle implementieren? Zum Beispiel möchte ich dem Benutzer der Vorlage sagen: Du kannst alles in meinem Container speichern, solange es die folgende Schnittstelle implementiert Init() y Destroy() Methoden.

Gracias

6voto

Konrad Rudolph Punkte 503837

Eine begrenzte Teilmenge der (beabsichtigten, aber leider gekürzten) C++0x-Funktionalität von Konzepten wird von der Boost Concept Check Bibliothek . Sie können sie nutzen, indem Sie eine Konzept-Check-Klasse für Ihre gewünschte Schnittstelle.

2voto

UncleBens Punkte 39755

Erstens, wenn Sie Init und Destroy benötigen, bedeutet dies, dass der Vorlagencode sie irgendwo verwendet. Das bedeutet, dass ihr Vorhandensein bereits vom Compiler überprüft wird, da die Vorlage nicht kompiliert werden kann, wenn der Typ nicht über diese Methoden verfügt.

Wenn man jedoch nach ihnen suchen möchte, könnte eine Möglichkeit darin bestehen, ihre Adressen in einem Kontext zur Kompilierzeit zu verwenden, z.B.

template <class T>
class X
{
private:
    template <unsigned N>
    struct Number {};
    Number<sizeof(&T::Init) + sizeof(&T::Destroy)> must_define_init_and_destroy();
};

struct A
{
    bool Init();
    void Destroy();
};

struct B {};

int main()
{
    X<A>();
    X<B>();
}

Bei Comeau ist die Ausgabe:

"ComeauTest.c", line 7: error: class "B" has no member "Init"
          Number<sizeof(&T::Init) + sizeof(&T::Destroy)> must_define_init_and_destroy();
                            ^
          detected during instantiation of class "X<T> [with T=B]" at line 21

"ComeauTest.c", line 7: error: class "B" has no member "Destroy"
          Number<sizeof(&T::Init) + sizeof(&T::Destroy)> must_define_init_and_destroy();
                                               ^
          detected during instantiation of class "X<T> [with T=B]" at line 21

Dies funktioniert jedoch nicht, wenn eine der erforderlichen Methoden überladen wird, und natürlich wird auch nicht geprüft, ob diese Methoden einen geeigneten Prototyp haben.

Vielleicht erwarten Sie z. B. bool Init(int, int). Sie könnten ein static_cast verwenden, um die exakte Signatur zu prüfen, aber auch dies könnte unnötige Einschränkungen für den Typ bedeuten. Was ist zum Beispiel, wenn eine Klasse stattdessen bool Init(long, long) hat?)

Auf die eine oder andere Weise scheint dieser Aufwand nur notwendig, um die Fehlermeldungen deutlicher zu machen. Ich bezweifle jedoch sehr, dass eine Meldung, die man sonst ohne Konzeptprüfungen erhalten würde (a la "keine geeignete Methode Init zum Aufruf mit T = X, wenn hier verwendet"), so schlecht ist.

1voto

Dario Punkte 47246

Nein, das ist nicht möglich.

Schablonen werden ersetzt durch eine Art und nicht mit vielen verschiedenen.

Erwägen Sie, eine Basisklasse zu erstellen, von der alle möglichen Mitglieder erben müssen, und lassen Sie alle Vorlagen weg.

Sie müssen im Wesentlichen Folgendes einführen existentielle Typen was in C++ nicht unterstützt wird.

0voto

Naveen Punkte 71443

Im aktuellen Standard nicht möglich. Ich glaube, es ist durch "Konzepte" möglich, die in C++0x zum Standard werden sollen (?).

0voto

gnud Punkte 75549

Nun, ich denke, Sie könnten eine Methode definieren, die Folgendes aufruft Init() y Destroy() auf das Vorlagenargument, und rufen Sie diese Methode irgendwie im Debug-Modus auf.

Alternativ können Sie auch eine Schnittstelle definieren und in Ihrer Vorlagenimplementierung auf diese Schnittstelle verweisen. Dies könnte auch im Freigabemodus deaktiviert werden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X