我正在使用模板函数进行对象构造以从反射数据创建对象,并且它工作得很好,但现在我想在反射系统中支持STL容器类型,以便对象如下:
// 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; };
可以支持.我可以在返回时做一些正则表达式魔法
typeid( object ).name()
确定一个对象是一个向量还是一个映射,以及该对象的参数参数是什么.我已经尝试了一些模板魔法来做类似下面的事情,其中CreateString,ConstructString& DestroyString代表函数,数据也支持使用类型数据库来处理对象构造的更复杂的东西.
// 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); }
由于与“vec-> push_back(* obj)”的非法间接,这不起作用;“我不能这样,因为我实际上并不知道这种类型.基本上我需要做的是创建这个向量,其中已经包含一些空白的未设置元素,或者在没有实际类型的情况下向其添加新元素,因为如果我可以获得指向向量内部的内存块的指针,我可以滚动并构造对象.但是向量添加了诸如的要求
vector::push_back( T& value )
要么
vector::insert( Iter&,T& )
除非我能从模板内部获取T类型,否则对我不起作用
测试代码的pastebin试图解决这个问题:
http://pastebin.com/1ZAw1VXg
所以我的问题是,当我在像这样的模板中时,如何获取std :: vector声明的std :: string部分
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)你要么利用std :: vector<>这个事实(与所有标准库容器类一样)维护一个成员类型value_type,它表示存储在向量中的元素的类型.所以你可以这样做:
template <typename T> void SomeFunc() { typename T::value_type s; // <--- declares a `std::string` object // if `T` is a `std::vector<std::string>` }
2)否则,您更改函数的声明并使用模板模板参数:
template <template <typename> class T,typename Elem> void SomeFunc(T<Elem> &arg) { Elem s; }
但是,有一个小问题:std :: vector实际上是一个带有两个参数(元素类型和分配器类型)的模板,这使得使用模板模板参数有点困难并且仍然保持语法简单.对我有用的一件事是声明一个只留下一个模板参数的矢量类型的别名:
template <typename Elem> using myvector = std::vector<Elem>;
然后我可以像这样使用SomeFunc:
int main() { myvec<std::string> vec; SomeFunc(vec); }