2017-11-28 3 views
0

Ich versuche, meinen Kopf darum zu wickeln, wie Vorlagenvorlagen funktionieren, um eine ähnliche Funktionalität zu implementieren, wie unten gezeigt.Vorlagenschablonen-Sammlung, die ein anderes Vorlagenargument akzeptiert

Betrachten Sie zwei Klassen (in Java). Die erste Klasse ist die Sammlung von pack-Methode zurück Begrenzung durch die Angabe, dass nur ein Objekt der zweiten Template-Argument kann darin gespeichert werden: für

abstract class ContainerPacker<T, Container extends Collection<T>> { 
    abstract Container pack(T t); 
} 

und Implementierung dieser Klasse, sagen wir mal, könnte Integer Typ dann aussehen wie folgt:

class IntegerContainerPacker extends ContainerPacker<Integer, List<Integer>> { 
    @Override 
    List<Integer> pack(Integer t) { 
     List<Integer> list = new ArrayList<>(t); 
     list.add(t); 
     return list; 
    } 
} 

Jetzt möchte ich etwas ähnliches in C++ mit Vorlagenvorlagen tun. Beachten Sie, wie die Container ist eine Vorlage selbst: wenn

template <typename T, template <typename U> class Container> 
class ContainerPacker { 
    public: 
    virtual Container<T> pack(T) = 0; 
}; 

Ich habe Probleme, es zu implementieren. Der folgende Code nicht kompiliert:

class IntegerVectorPacker : public ContainerPacker<int, std::vector> { 
    public: 
    std::vector<int> pack(int t) { 
     std::vector<int> v = std::vector<int>(); 
     v.push_back(t); 
     return v; 
    } 
}; 

Die Fehler sind:

error: type/value mismatch at argument 2 in template parameter list for ‘template class Container> class ContainerPacker’ class IntegerVectorPacker : public ContainerPacker {

und

note: expected a template of type ‘template class Container’, got ‘template class std::vector’

Ich habe nach einer Antwort gesucht, aber es ist auch schwierig, herauszufinden, was Frage Fragen. Vorlagenvorlagen sind schwer.

+1

Der zweite Fehler, den Sie erwähnen, scheint damit zu tun zu sein, dass Sie 'std :: vector' als zweiten Template-Parameter angeben, anstatt die Vollspezialisierung anzugeben, die' std :: vector 'ist. Es wird gesagt, dass es eine Vorlagenklasse erwartet, aber Sie haben einen Klassennamen angegeben. – Howard

Antwort

1

Versuchen mit

template <typename T, template <typename...> class Container> 

Das Problem (? Problem) in Ihrem Code ist, dass std::vector eine Template-Klasse ist, die mehr als ein Argument Vorlagen erhalten (zwei: die zweite einen Standardtyp hat); passt also nicht zu Container.

definieren Container als Empfang null oder mehr Vorlagen sollte das Spiel mit std::vector<int> erlauben (das ist wirklich std::vector<int, std::allocator<int>>) und andere Behälter.

- EDIT -

Ich sehe jetzt, dass Sie Tagger diese Frage C++ haben und nicht C++ 11 (oder höher).

Der Vorschlag typename... ist nur gültig ab C++ 11, da variadic Vorlagen nicht verfügbar sind.

Für 98 C++ können Sie

template <typename T, template <typename, typename> class Container> 

schreiben, aber dies nur mit zwei Parametern Containern arbeitet.

- EDIT 2-

Off Topic Vorschlag.

Wenn Sie C++ 11 oder neuer (so variadische Vorlagen) verwenden können, schalten Sie die Reihenfolge der Container und T für ContainerPacker und verwandeln T ist ein variadische Packung; etwas wie

template <template <typename...> class Container, typename ... Ts> 
class ContainerPacker { 
    public: 
    virtual Container<Ts...> pack(Ts...) = 0; 
}; 

Es ist viel flexibler.

+0

Oh, das ist perfekt! Ich habe bemerkt, dass es mehrere Vorlagenargumente hat, aber die zweite ist voreingestellt, also dachte ich, dass sie weggelassen werden kann. Wie auch immer, es funktioniert, danke (: – Jezor

+1

@Jezor - Hinzugefügt einen Off-Thema Vorschlag (falls Sie C++ 11 oder neuer verwenden können) – max66

+0

Nochmals vielen Dank (: Ich benutze C++ 11 und eigentlich, ich ' Ich habe mich gefragt, wie man andere Template-Argumente in der Implementierung spezifiziert. – Jezor

Verwandte Themen