テンプレート化されたtypedef?
質問
CおよびC ++のガベージコレクターであるlibgcを使用しています。 STLコンテナをガベージコレクションにするには、gc_allocatorを使用する必要があります。
書く代わりに
std::vector<MyType>
書かなければならない
std::vector<MyType,gc_allocator<MyType> >
のようなものを定義する方法はありますか
template<class T> typedef std::vector<T,gc_allocator<T> > gc_vector<T>;
しばらく前に確認しましたが、不可能であることがわかりました。しかし、私は間違っているか、別の方法があるかもしれません。
この方法でマップを定義することは特に不愉快です。
std::map<Key,Val>
なる
std::map<Key,Val, std::less<Key>, gc_allocator< std::pair<const Key, Val> > >
編集:マクロの使用を試みた後、次のコードがそれを壊すことがわかりました:
#define gc_vector(T) std::vector<T, gc_allocator<T> >
typedef gc_vector( std::pair< int, float > ) MyVector;
テンプレート化された型定義内のコンマは、マクロ引数セパレーターとして解釈されます。
だから、内部クラス/構造が最良の解決策のようです。
これは、C ++ 0Xでどのように行われるかの例です
// standard vector using my allocator
template<class T>
using gc_vector = std::vector<T, gc_allocator<T> >;
// allocates elements using My_alloc
gc_vector <double> fib = { 1, 2, 3, 5, 8, 13 };
// verbose and fib are of the same type
vector<int, gc_vector <int>> verbose = fib;
解決
using
を使用して、C ++ 11テンプレート化された型エイリアスを使用できます。このように
template <typename T>
using gc_vector = std::vector<T, gc_allocator<T>>;
注:これは古い質問ですが、かなり多くの賛成票があり、検索結果に表示されるため、更新された回答に値すると思いました。
他のヒント
<!> quot; templated typedef <!> quot;は使用できませんが、内部型で便利なクラス/構造体を使用できます:
template<typename T>
struct TypeHelper{
typedef std::vector<T,gc_allocator<T> > Vector;
};
そしてコードで使用
TypeHelper<MyType>::Vector v;
TypeHelper<MyType>::Vector::iterator it;
また、マップについても同様です:
template<typename K,typename V>
struct MapHelper{
typedef std::map<K, V, gc_allocator<K,V> > Map;
};
編集-@Vijay:別の可能な回避策があるかどうかわかりません。それが私がそれを行う方法です。マクロはよりコンパクトな表記法を提供するかもしれませんが、個人的には気に入らないでしょう:
#define GCVECTOR(T) std::vector<T,gc_allocator<T> >
編集-@chmike:TypeHelper
解決策ではではありません、コンストラクタを再定義する必要はありません!
パブリックに継承できます:
template<class T>
class gc_vector<T> : public std::vector<T, gc_allocator<T> >
{
public:
// You'll have to redeclare all std::vector's constructors here so that
// they just pass arguments to corresponding constructors of std::vector
};
これにより、問題が完全に解決されます。派生型は、基本型を使用できるすべての場所で使用でき、適切なコンパイラーによる実装オーバーヘッドはありません。
std :: vectorに非仮想デストラクタがあるという事実は、ベースクラス変数へのポインタを介して派生クラス変数を削除しようとすると、C ++標準に従って未定義の動作を引き起こす可能性があります。
実世界では、これはこの特定のケースでは重要ではありません。派生クラスには基本クラスと比較して新しいものは何も追加されないため、派生クラスのデストラクタは基本クラスのデストラクタを呼び出すだけです。とにかく慎重に移植してください。
このクラス変数をヒープに割り当てない場合(そして、スタック上に、他のクラスのメンバーとしてベクトル変数を割り当てるのが一般的です)、非仮想デストラクタの問題は影響しません。
コンパイラを限界までプッシュしたい場合は、MACROで実行できます。 Javaの<!> quot; Future <!> quot;に対応するC ++を実装しながら、それを行いました。および<!> quot; Callable <!> quot;クラス。ライブラリは参照カウントされたオブジェクトを使用するため、<!> quot; Reference <!> lt; T <!> gt; <!> quot;それ自体は<!> quot; T <!> quot;のテンプレートクラスです。 <!> quot; ReferencedObject <!> quot;から派生。
1. Create your template Classes. Mine are:
template<typename T>
class Callable {
private:
public:
virtual T Call() = 0;
};
template<typename T> CountedFuture : public ReferencedObject {
private:
Callable<T>* theTask;
T theResult;
public:
T Get() {
// Run task if necessary ...
if(task) {
theResult = theTask->Call();
delete theTask;
}
return theResult;
}
};
2. In the application code I'm using references, so I define the macro:
#define Future(T) Reference<CountedFuture<T>>
これの利点は、マクロが<!> quot; template typedef <!> quot;から望んでいることを正確に実行することです。<!> quot; < !> lt; <!> gt; <!> quot;型パラメーターの場合、型の推論はありません。
3. I can now use the Macro wherever I would use a template, like in functions:
Future(char*) DoSomething() { ... }
bool TestSomething(Future(std::string) f) { .... }