【问题标题】:C++ Get Vector typeC++ 获取向量类型
【发布时间】:2012-09-11 12:19:59
【问题描述】:

我正在使用模板函数进行对象构造,从反射数据创建对象,效果很好,但现在我想在反射系统中支持 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添加了诸如

之类的要求
vector::push_back( T& value ) 

vector::insert( Iter&, T& ) 

除非我能从模板中得到那个 T 类型,否则对我不起作用

粘贴测试代码来尝试解决这个问题: 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>>>();

【问题讨论】:

  • std::vector 有一个内部 typedef T value_type,如果这是你需要的。

标签: c++ templates vector


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    有两种方法可以做到这一点。

    1) 要么你利用std::vector&lt;&gt;(像所有标准库容器类一样)维护一个成员类型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);
    }
    

    【讨论】:

    • 谢谢你,它可以让我制作一个比我已经破解的解决方案更简洁的函数版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    • 2016-08-30
    • 2022-01-16
    • 1970-01-01
    相关资源
    最近更新 更多