简体   繁体   中英

C++ Get Vector type

I'm using template functions for object construction to create objects from reflection data, and it works pretty well, but now I want to support STL container types in the reflection system so that objects such as:

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

Can be supported. I can do some regex magic on the return of

typeid( object ).name() 

to figure out if an object is a vector or a map, and what the parameter arguments for the object is. And I have tried some template magic to do it something like the following, where CreateString, ConstructString & DestroyString are stand in functions and the data is stand in as well for something a bit more complex that uses a type database to handle object construction.

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

}

Which doesn't work owing to the illegal indirection with "vec->push_back(*obj);"which I can't case because I don't actually know the type. Basically what I need to be able to do is create this vector with some blank unset elements already in it, or add new elements to it without actually having the type, because if I can get a pointer to a memory block inside the vector I can roll with that and construct the object. But the vector add requirements such as

vector::push_back( T& value ) 

or

vector::insert( Iter&, T& ) 

Won't work for me unless I can get my hands on that T type from inside the template

pastebin of testing code to try and solve this: http://pastebin.com/1ZAw1VXg

So my question is, how can I get the std::string part of a std::vector declaration when I'm inside a template like

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

There are two ways to accomplish this.

1) Either you make use of the fact that std::vector<> (like all standard library container classes) maintains a member type value_type , which represents the type of the elements stored in the vector. So you can do this:

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

2) Or else, you change the declaration of your function and make use of template template parameters:

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

However, there is a small problem with that: std::vector is really a template with two parameters (element type and allocator type), which makes it a little difficult to use the template template parameters and still keep the syntax simple. One thing that worked for me is to declare an alias of the vector type that leaves only one template parameter:

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

Then I can use SomeFunc like this:

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

在 c++11 中,你可以使用 decltype 和 std::decay 来达到这个效果:

std::vector<int> vec; using T = typename std::decay<decltype(*vec.begin())>::type;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM