Frage

In C # können wir eine generische Art definieren, die Beschränkungen für die Art auferlegt, die als generischer Parameter verwendet werden kann. Das folgende Beispiel zeigt die Verwendung von generischen Einschränkungen:

interface IFoo
{
}


class Foo<T> where T : IFoo
{
}

class Bar : IFoo
{
}

class Simpson
{
}

class Program
{
    static void Main(string[] args)
    {
        Foo<Bar> a = new Foo<Bar>();
        Foo<Simpson> b = new Foo<Simpson>(); // error CS0309
    }
}

Gibt es eine Möglichkeit wir Einschränkungen für Template-Parameter in C ++ durchsetzen können.


C ++ 0x hat native Unterstützung für diese, aber ich spreche über aktuellen Standard C ++.

War es hilfreich?

Lösung

Wie jemand anderes erwähnt hat, C ++ 0x wird diese in die Sprache eingebaut bekommen. Bis dahin würde ich Bjarne Stroustrup 's Vorschläge für template Einschränkungen .

Edit: auch Erhöhung hat eine Alternative eigener .

Edit2: Sieht aus wie Konzepte von C ++ 0x entfernt wurden .

Andere Tipps

Wenn Sie C ++ 11, Sie static_assert mit std::is_base_of für diesen Zweck verwenden können.

Beispiel:

#include <type_traits>

template<typename T>
class YourClass {

    YourClass() {
        // Compile-time check
        static_assert(std::is_base_of<BaseClass, T>::value, "type parameter of this class must derive from BaseClass");

        // ...
    }
}

„Implizit“ ist die richtige Antwort. Vorlagen effektiv ein „Duck Typing“ Szenario aufgrund der Art und Weise schaffen, in dem sie erstellt werden. Sie können alle Funktionen aufrufen Sie auf Vorlage typisierte Wert gewünscht wird, und die einzigen instantiations, die denen angenommen werden, sind für die dieses Verfahren definiert ist. Zum Beispiel:

template <class T>
int compute_length(T *value)
{
    return value->length();
}

Wir können auf jeden Typ auf einem Zeiger diese Methode aufrufen, die die length() Methode deklariert eine int zurückzukehren. Thusly:

string s = "test";
vector<int> vec;
int i = 0;

compute_length(&s);
compute_length(&vec);

... aber nicht auf einen Zeiger auf eine Art, die tut nicht erklären length():

compute_length(&i);

Das dritte Beispiel wird nicht kompiliert.

Das funktioniert, weil C ++ eine neue Version der templatized Funktion kompiliert (oder Klasse) für jede Instanziierung. Da es diese Zusammenstellung führt, macht es eine direkte, fast Makro wie Substitution der Vorlage Instanziierung in den Code vor der Kontrolle zu geben. Wenn alles nach wie vor mit dieser Vorlage funktioniert, dann Kompilation Erlös und wir schließlich zu einem Ergebnis kommen. Wenn etwas (wie int* nicht erklärt length()) ausfällt, dann erhalten wir die gefürchteten sechs Seitenvorlage kompilieren Zeitfehler.

Sie können auf IFoo einen Wächter Art setzen, die nichts tut, stellen Sie sicher, dass es da auf T in Foo:

class IFoo
{
public:
    typedef int IsDerivedFromIFoo;
};

template <typename T>
class Foo<T>
{
    typedef typename T::IsDerivedFromIFoo IFooGuard;
}

Schauen Sie sich Erhöhung

  

Die Boost Concept Check Library (BCCL)

     

Das Concept Check Bibliothek ermöglicht eine ausdrückliche Anweisung und Kontrolle der Konzepte hinzufügen im Stil der vorgeschlagener C ++ Spracherweiterung .

Eine Art. Wenn Sie auf einen IFoo * static_cast, dann wird es unmöglich sein, die Vorlage zu instanziieren, wenn der Anrufer eine Klasse übergibt, der * zu einem IFoo zugeordnet werden kann.

Nur implizit.
Jede Methode verwenden Sie in einem Verfahren, das tatsächlich aufgerufen wird, auf dem Template-Parameter auferlegt.

Sie können es tun. Erstellen Sie die Basisvorlage. Machen Sie es nur private Konstruktoren haben. Dann erstellen Sie Spezialisierungen für jeden Fall Sie zulassen möchten (oder das Gegenteil machen, wenn die Sperrliste viel kleiner als die erlaubten Liste ist).

Der Compiler wird nicht zulassen, dass Sie die Vorlagen instanziiert, die die Version mit einem eigenen Konstrukteuren nutzen.

In diesem Beispiel wird nur erlauben Instanziierung mit int und float.

template<class t> class FOO { private: FOO(){}};

template<> class FOO<int>{public: FOO(){}};

template<> class FOO<float>{public: FOO(){}};

Es ist nicht eine kurze und elegante Art und Weise, es zu tun, aber es ist möglich.

Sehen Sie sich das CRTP Muster (Merkwürdiger Recursive Template Pattern). Es soll dazu beitragen, statische inheritence zu unterstützen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top