2012-09-19 13 views
6

Uso le funzioni dei modelli per la costruzione di oggetti per creare oggetti dai dati di riflessione e funziona piuttosto bene, ma ora voglio supportare i tipi di contenitore STL nel sistema di riflessione in modo che oggetti come:C++ Tipo vettoriale

// 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; 
}; 

Può essere supportato. Posso fare qualche magia regex sul ritorno di

typeid(object).name() 

di capire se un oggetto è un vettore o di una mappa, e ciò che gli argomenti dei parametri per l'oggetto. E ho provato alcuni modelli magici per fare qualcosa del genere, in cui CreateString, ConstructString & DestroyString hanno funzioni e i dati sono validi anche per qualcosa di un po 'più complesso che utilizza un database di tipi per gestire la costruzione di oggetti.

// 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); 

} 

che non funziona a causa della indirezione illegale con "vec-> push_back (* obj);" quale non posso caso perché in realtà non conosco il tipo. Fondamentalmente quello che devo essere in grado di fare è creare questo vettore con alcuni elementi nonset vuoti già presenti in esso, o aggiungere nuovi elementi senza avere effettivamente il tipo, perché se riesco a ottenere un puntatore su un blocco di memoria all'interno del vettore posso rotolare con quello e costruire l'oggetto. Ma il vettore di aggiungere requisiti quali

vector::push_back(T& value) 

o

vector::insert(Iter&, T&) 

non funziona per me, se non riesco a mettere le mani su quel tipo T dall'interno del modello

pastebin di testare il codice per cercare di risolvere questo: http://pastebin.com/1ZAw1VXg

Quindi la mia domanda è, come posso ottenere la parte std :: string di una dichiarazione std :: vector quando sono all'interno di un modello come

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

Lo std :: VECTOR' ' ha un 'typedef T value_type' interiore se questo è ciò che ti serve. –

risposta

15

Ci sono due modi per farlo.

1) O si fanno uso di fatto che std::vector<> (come tutte le classi contenitore libreria standard) mantiene un tipo di membro value_type, che rappresenta il tipo di elementi memorizzati nel vettore. Così si può fare questo:

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

2) Oppure, si modifica la dichiarazione della funzione e fare uso di parametri di modello di modello:

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

Tuttavia, c'è un piccolo problema con che: std::vector è davvero un modello con due parametri (tipo di elemento e tipo di allocatore), il che rende un po 'difficile utilizzare i parametri del modello di modello e mantenere la sintassi semplice.Una cosa che ha lavorato per me è dichiarare un alias del tipo vettore che lascia parametro solo un modello:

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

poi posso usare SomeFunc come questo:

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

Grazie per quello, mi permetterà di realizzare una versione della funzione molto più pulita della soluzione che ho violato. – kyall