2008-09-10 15 views
2

Ich habe eine Klasse, die eine Wrapper-Klasse (dient als eine gemeinsame Schnittstelle) um eine andere Klasse, die die erforderliche Funktionalität implementiert. Also sieht mein Code so aus.Überprüfung der Vererbung mit Vorlagen in C++

template<typename ImplemenationClass> class WrapperClass { 
// the code goes here 
} 

Nun, wie kann ich sicherstellen, dass ImplementationClass nur, ähnlich wie Java-Generika-

<? extends BaseClass> 

Syntax aus einem Satz von Klassen abgeleitet werden?

Antwort

7

Es ist ausführlich, aber man kann es wie folgt tun:

#include <boost/utility/enable_if.hpp> 
#include <boost/type_traits/is_base_of.hpp> 

struct base {}; 

template <typename ImplementationClass, class Enable = void> 
class WrapperClass; 

template <typename ImplementationClass> 
class WrapperClass<ImplementationClass, 
     typename boost::enable_if< 
     boost::is_base_of<base,ImplementationClass> >::type> 
{}; 

struct derived : base {}; 
struct not_derived {}; 

int main() { 
    WrapperClass<derived> x; 

    // Compile error here: 
    WrapperClass<not_derived> y; 
} 

Diese für den Standard eines Compilers mit guter Unterstützung erfordert (letzte Compiler sollte in Ordnung sein, aber alte Versionen von Visual C++ wird nicht sein) . Weitere Informationen finden Sie unter Boost.Enable_If documentation.

Als Ferruccio sagte, eine einfachere, aber weniger leistungsstarke Umsetzung:

#include <boost/static_assert.hpp> 
#include <boost/type_traits/is_base_of.hpp> 

struct base {}; 

template <typename ImplementationClass> 
class WrapperClass 
{ 
    BOOST_STATIC_ASSERT((
     boost::is_base_of<base, ImplementationClass>::value)); 
}; 
+0

Sie können es mit BOOST_STATIC_ASSERT an Stelle von enable_if etwas klarer machen. d.h. BOOST_STATIC_ASSERT (boost :: is_base_of ); – Ferruccio

+0

Ja, ich habe das hinzugefügt. Ich bevorzuge enable_if, da Sie verschiedene Versionen haben und etwas bessere Fehlermeldungen (IMO) erhalten. Manche Leute mögen auch die Fehlermeldungen von MPLs statischem Assert. –

+0

Danke, das hat funktioniert :) – JSN

2

In der aktuellen Lage der Dinge gibt es keinen anderen Weg als durch Kommentare oder eine Drittanbieter-Lösung. Boost bietet hierfür eine concept check library an, und ich denke, gcc hat auch eine Implementierung. Konzepte sind auf der Liste der C++ 0x-Verbesserungen, aber ich bin mir nicht sicher, ob Sie Subtypen angeben können - sie sind mehr für "müssen diese Operationen unterstützen", die (ungefähr) äquivalent ist.

Bearbeiten: Wikipedia hat diese section über Konzepte in C++ 0x, die wesentlich einfacher zu lesen als Entwürfe sind.

0

Stoustrup's own words on the subject See.

Grundsätzlich eine kleine Klasse, die Sie irgendwo instanziieren, z. der Konstruktor für Templates.

template<class T, class B> struct Derived_from { 
    static void constraints(T* p) { B* pb = p; } 
    Derived_from() { void(*p)(T*) = constraints; } 
};