模板化的typedef?

我正在使用libgc,C和C ++的垃圾收集器。 要使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> > > 

编辑:在尝试使用macros后,我发现下面的代码打破了它:

 #define gc_vector(T) std::vector<T, gc_allocator<T> > typedef gc_vector( std::pair< int, float > ) MyVector; 

模板types定义中的逗号被解释为macros参数分隔符。

所以看起来,内部类/结构是最好的解决scheme。

这里是一个关于如何在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; 

你不能使用“模板化的typedef”,但你可以使用一个便利的类/结构与内部types:

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

编辑 – @维杰:我不知道是否有另一种可能的解决方法,这就是我将如何做; 一个macros可能会给你一个更简洁的符号,但我个人不喜欢它:

 #define GCVECTOR(T) std::vector<T,gc_allocator<T> > 

编辑 – @chmike:请注意TypeHelper解决scheme要求您重新定义构造函数!

你可以使用像这样使用C ++ 11模板types别名

 template <typename T> using gc_vector = std::vector<T, gc_allocator<T>>; 

注:我知道这是一个古老的问题,但由于它有很多upvotes,并在search结果中出现,我认为它值得一个更新的答案。

你可以公开inheritance:

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

这完全解决了你的问题。 派生types可以在任何可以使用基types的地方使用,并且没有任何体面编译器的实现开销。

std :: vector具有非虚拟析构函数的事实可能会导致根据C ++标准的未定义行为,如果您尝试通过指向基类variables的指针删除派生类variables。

在现实世界中,在这种情况下这应该不重要 – 派生类与基类相比没有任何新增function,因此派生类的析构函数只是调用基类的析构函数。 无论如何,继续执行偏执狂,端口。

如果你永远不会在堆上分配这个类variables(并且通常在堆栈上分配vectorvariables,并且作为其他类的成员),非虚拟析构函数问题不会影响到你。

如果你愿意把你的编译器推到极限,可以用MACRO来完成。 我在为Java的“Future”和“Callable”类实现C ++等同的时候做了这个。 我们的库使用引用计数的对象,所以“Reference <T>”本身就是一个模板类,其中“T”从“ReferencedObject”派生。

 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>> 

这样做的好处在于,macros从“模板types定义”(template typedef)完全可以达到你想要的效果,缺点是你不能使用“<>”作为你的types参数,也没有types推断。

 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) { .... }