12

オブジェクト構築にテンプレート関数を使用してリフレクションデータからオブジェクトを作成していますが、これは非常にうまく機能しますが、リフレクションシステムで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タイプを手に入れることができなければ、私にはうまくいきません

これを解決するためのテストコードのペーストビン: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>>>();
4

2 に答える 2

28

これを行うには 2 つの方法があります。

1)std::vector<> (すべての標準ライブラリ コンテナ クラスと同様に)value_typeベクトルに格納されている要素の型を表す member 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実際には 2 つのパラメーター (要素の型とアロケーターの型) を持つテンプレートであるため、テンプレートのテンプレート パラメーターを使用して構文を単純に保つことが少し難しくなります。私にとってうまくいったことの1つは、テンプレートパラメーターを1つだけ残すベクター型のエイリアスを宣言することです。

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

次に、次SomeFuncのように使用できます。

int main()
{
  myvec<std::string> vec;
  SomeFunc(vec);
}
于 2012-09-19T07:54:25.047 に答える