2012-09-19 11 views
6

Ich verwende Template-Funktionen für die Objektkonstruktion, um Objekte aus Reflektionsdaten zu erstellen, und es funktioniert ziemlich gut, aber jetzt möchte ich STL-Containertypen im Reflektionssystem unterstützen, so dass Objekte wie:C++ Get Vektortyp

// Note - test case only 
// for real world usage it would probably not be structured like this 
// and the phrases would be mapped by an id or something 
struct Phrases { 
    std::vector<std::string> phrases; 
}; 

typedef std::string Lang; 
struct Langs { 
    std::map< Lang, Phrases > translations; 
}; 

Kann unterstützt werden. Ich kann über die Rückgabe von

typeid(object).name() 

, um herauszufinden, einige regex Magie tun, wenn ein Objekt einen Vektor oder eine Karte ist, und was die Parameter Argumente für das Objekt ist. Und ich habe einige Vorlagen Magie versucht, es so etwas wie die folgenden zu tun, wo CreateString, ConstructString & DestroyString in Funktionen stehen und die Daten stehen auch für etwas ein bisschen komplexer, die eine Typ-Datenbank verwendet, um Objektkonstruktion zu behandeln.

// Representational of code, basically a copy-paste to a different test project where I can work out the problems with this specific vector problem 
// Vector specialised construction 
template <typename T> void ConstructVector(void* object, const std::vector<std::string>& data) { 
    T* vec = (T*)object; 
    Name vector_type = GetVectorTypeName<T>(); 

    void *obj; 
    CreateString(&obj); 
    // All fields in this type should be valid objects for this vector 
    for(std::vector<std::string>::const_iterator it = data.begin(), end = data.end(); it != end; ++it) { 
    // Push it 
    vec->push_back(*obj); 
    // Get address to new instance 
    void *newly = &vec->back(); 
    ConstructString(newly,*it); 
    } 
    DestroyString(&obj); 

} 

Welche funktioniert nicht mit der illegalen indirection wegen "vec-> push_back (* obj);" was ich nicht kann, weil ich den Typ eigentlich nicht kenne. Grundsätzlich muss ich in der Lage sein, diesen Vektor mit einigen leeren Elementen zu erstellen, die bereits darin enthalten sind, oder neue Elemente hinzuzufügen, ohne den Typ zu haben, denn wenn ich einen Zeiger auf einen Speicherblock innerhalb des Vektors bekommen kann, kann ich das tun Rolle damit und baue das Objekt. Aber der Vektor Anforderungen hinzufügen wie

vector::push_back(T& value) 

oder

vector::insert(Iter&, T&) 

Wird nicht für mich arbeiten, wenn ich meine Hände auf diesem T-Typ bekommen kann aus dem Inneren der Vorlage

Pastebin Testcode um zu versuchen und zu lösen: http://pastebin.com/1ZAw1VXg

So ist meine Frage, wie ich den std :: string Teil einer std :: vector Erklärung erhalten kann wenn ich in einer Vorlage wie

bin
template <typename T> void SomeFunc() { 

    // Need to get std::string here somehow  
    // Alternatively need to make the vector a certain size and then 
    // get pointers to it's members so I can construct them 
} 


SomeFunc<std::vector<std::string>>>(); 
+1

Die 'std :: VECTOR' hat einen inneren 'typedef T value_type', wenn Sie das brauchen. –

Antwort

15

gibt es zwei Möglichkeiten, dies zu erreichen.

1) Entweder man sich die Tatsache zunutze machen, dass std::vector<> (wie alle Standardbibliotheken Containerklassen) unterhält einen Elementtyp value_type, die in dem Vektor, der die Art der Elemente gespeichert darstellt. So können Sie dies tun:

template <typename T> void SomeFunc() { 
    typename T::value_type s; // <--- declares a `std::string` object 
          //  if `T` is a `std::vector<std::string>` 
} 

2) Oder aber, Sie die Deklaration Ihrer Funktion ändern und die Verwendung von Template-Template-Parameter machen:

template <template <typename> class T, typename Elem> 
void SomeFunc(T<Elem> &arg) 
{ 
    Elem s; 
} 

Allerdings gibt es ein kleines Problem mit Das: std::vector ist wirklich eine Vorlage mit zwei Parametern (Elementtyp und Zuordnungstyp), was es ein wenig schwierig macht, die Template-Template-Parameter zu verwenden und dennoch die Syntax einfach zu halten.Eine Sache, die für mich gearbeitet ist ein Alias ​​des Vektors Typ zu deklarieren, die nur ein Template-Parameter lässt:

template <typename Elem> 
using myvector = std::vector<Elem>; 

Dann kann ich SomeFunc wie folgt verwenden:

int main() 
{ 
    myvec<std::string> vec; 
    SomeFunc(vec); 
} 
+0

Danke dafür, es erlaubt mir eine viel sauberere Version der Funktion als die Lösung, die ich gehackt habe. – kyall