2016-05-04 6 views
1

Ich mache eine Fabrik "M". Ich muss eine Klasse "C" konstruieren. Der Entwickler, der meine Klasse 'M' enthält, möchte 'M :: getInst()' aufrufen können und eine korrekt konstruierte Instanz von 'C' haben.Ist es für eine Klasse möglich, ein Parameterpaket verfügbar zu machen?

Zusätzlich möchte ich den Schreiber von 'C' in der Lage sein, mit uns zu arbeiten, indem wir absolut nichts tun, außer einen öffentlichen Konstruktor zur Verfügung zu stellen, und eine einzelne Hilfsmethode, die meiner Klasse 'M' sagt, wie man das findet Konstrukteur.

Ist das möglich? Das Folgende ist das was ich prinzipiell machen möchte. Das Problem ist, dass ich in C++ keine Möglichkeit sehe, die Methode "types()" zu schreiben. Es scheint unmöglich, Typen (sogar einen!) Als Wert zurückzugeben.

struct C { 
    String s; Blob b; 
    C(String a, Blob b) : s(a), b(b) {} 
    typelist types() { 
     return { String, Blob }; 
    } 
}; 

clas M { 
    template<typename T> 
    T* getInst() { 
     return getInst_imp<T::types()>(); 
    }; 

    template<class... Ks> 
    T* getInst_imp() { 
     return T(getValue(Ks)...); 
    } 
}; 

Welche, vom Anwender aufgerufen werden würde, wie:

C* instance = M::getInst<C>(); 

Der Grund dafür ist, dass ‚C‘ wird aus Komponenten aus einem festen Satz von Komponententypen gebaut. Meine Klasse 'M' ist die Autorität, wie man sie initialisiert. Es macht also Sinn, jedes Mal, wenn ein Entwickler ein neues Aroma von C kreieren möchte, alle bestehenden Räder neu zu erfinden? Sie sollten M einfach sagen, welche Komponenten sie brauchen. Aber wie geht das?

Antwort

1

Eric Niebler suggests sollte eine Typliste definiert werden als:

// A class template that is just a list of types: 
template <class... T> struct typelist { }; 

, die Sie auf Ihre Klasse aussetzen kann C:

struct C { 
    String s; 
    Blob b; 
    C(String a, Blob b) : s(a), b(b) {} 
    using types = typelist<String, Blob>; 
}; 

Dann können wir einige Techniken aus Erics Tiny Metaprogrammierung Bibliothek ausleihen, um die Typliste zu verwenden, in Ihrer Fabrik:

template<typename T, typename List> 
struct MImpl; 

template<typename T, typename ...Ks> 
struct MImpl<T, typelist<Ks...>> { 
    static T getInst() { 
     return T(getValue<Ks>()...); 
    } 
}; 

class M { 
public: 
    template<typename T> 
    T getInst() { 
     return MImpl<T, typename T::types>::getInst(); 
    } 
}; 

Live demo.

+0

Das ist perfekt! Ich hatte versucht, etwas Ähnliches zu machen, aber ich habe nie daran gedacht, den Typedef zu verwenden - ich habe versucht, die Klassen selbst zu erstellen. Ich dachte, es wäre eine Sackgasse, weil der "Benutzer" sie spezialisieren musste, bevor sie verwendet werden konnten. Aber der Typdef gibt C-Autor einen Ort, um diese Informationen zu speichern. Vielen Dank! – SaburoutaMishima

1

Beste Sie können jetzt tun, ist std::tuple:

using typelist = std::tuple<String, Blob>; 
typelist types() { 
    return typelist(s, b); 
} 

, die je nachdem, was Sie tun, als tuple Literatur besser sein können.

+0

Ist das Tupel immer noch auf 10 Elemente beschränkt? Wir können nach einer Lib suchen, die eine größere Tupelklasse hat, oder eher unser eigenes Tupel rollt ... Glaubst du, es gibt einen anderen Weg, dies im Allgemeinen zu erreichen? Ich frage mich, ob ich eine schlechte Herangehensweise entwickelt habe. – SaburoutaMishima

+0

@Saburouta Huh? Ein Tupel war nie in der Anzahl der Elemente beschränkt. – Barry

+0

@Barry Warum sagst du * gerade *? Gibt es Pläne, ein Parameterpaket auf andere Weise exportieren zu lassen? Nur neugierig. Vielen Dank. – skypjack