C++ 模板类型定义?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/649718/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
templated typedef?
提问by chmike
I'm using libgc, a garbage collector for C and C++. To make STL containers garbage collectible one must use the gc_allocator.
我正在使用 libgc,一个用于 C 和 C++ 的垃圾收集器。要使 STL 容器可垃圾回收,必须使用 gc_allocator。
Instead of writing
而不是写作
std::vector<MyType>
one has to write
一个必须写
std::vector<MyType,gc_allocator<MyType> >
Could there be a way to define something like
有没有办法定义类似的东西
template<class T> typedef std::vector<T,gc_allocator<T> > gc_vector<T>;
I checked some time ago and found out it was not possible. But I may have been wrong or there might be another way around.
我前段时间检查过,发现这是不可能的。但我可能错了,或者可能有另一种方式。
Defining maps in this way is particularly unpleasing.
以这种方式定义地图尤其令人不快。
std::map<Key,Val>
becomes
变成
std::map<Key,Val, std::less<Key>, gc_allocator< std::pair<const Key, Val> > >
EDIT: After trying the use of macro I found out the following code breaks it:
编辑:尝试使用宏后,我发现以下代码破坏了它:
#define gc_vector(T) std::vector<T, gc_allocator<T> >
typedef gc_vector( std::pair< int, float > ) MyVector;
The comma inside the templated type definition is interpreted as a macro argument separator.
模板化类型定义中的逗号被解释为宏参数分隔符。
So it seems the inner class/struct is the best solution.
所以看起来内部类/结构是最好的解决方案。
Here is an example on how it will be done in C++0X
这是一个关于如何在 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;
回答by Snps
You can use C++11 templated type aliasing using using
e.g. like this
您可以使用using
例如这样的C++11 模板化类型别名
template <typename T>
using gc_vector = std::vector<T, gc_allocator<T>>;
Note: I know this is an old question but since it has quite many upvotes and as it turns up in search results I thought it deserved an updated answer.
注意:我知道这是一个老问题,但由于它有很多赞成票,而且当它出现在搜索结果中时,我认为它应该得到更新的答案。
回答by Paolo Tedesco
You cannot use a "templated typedef", but you can use a convenience class/struct with an inner type:
您不能使用“模板化 typedef”,但您可以使用具有内部类型的便利类/结构:
template<typename T>
struct TypeHelper{
typedef std::vector<T,gc_allocator<T> > Vector;
};
and then use in your code
然后在您的代码中使用
TypeHelper<MyType>::Vector v;
TypeHelper<MyType>::Vector::iterator it;
And something similar for the map:
和地图类似的东西:
template<typename K,typename V>
struct MapHelper{
typedef std::map<K, V, gc_allocator<K,V> > Map;
};
EDIT - @Vijay: I don't know if there's another possible workaround, that's how I would do it; a macro might give you a more compact notation, but personally I wouldn't like it:
编辑 - @Vijay:我不知道是否还有其他可能的解决方法,我就是这样做的;宏可能会给你一个更紧凑的符号,但我个人不喜欢它:
#define GCVECTOR(T) std::vector<T,gc_allocator<T> >
EDIT - @chmike: Please note that the TypeHelper
solution does notrequire you to redefine constructors!
编辑- @chmike:请注意,该TypeHelper
解决方案不要求你重新定义构造函数!
回答by sharptooth
You can publicly inherit:
您可以公开继承:
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
};
This solves your problem completely. The derived type can be used everywhere where the base type can be used, and there's no implementation overhead with any decent compiler.
这完全解决了您的问题。派生类型可以在任何可以使用基类型的地方使用,并且任何像样的编译器都没有实现开销。
The fact that std::vector has non-virtual destructor might lead to undefined behaviour according to C++ standard if you ever try to delete a derived class variable through a pointer to base class variable.
如果您尝试通过指向基类变量的指针删除派生类变量,则 std::vector 具有非虚拟析构函数的事实可能会导致根据 C++ 标准的未定义行为。
In real world this shouldn't matter in this particular case - the derived class has nothing new added compared to the base class and therefore the destructor for the derived class just calls the destructor for the base class. Proceed with paranoia, port carefully anyway.
在现实世界中,这在这种特殊情况下应该无关紧要 - 与基类相比,派生类没有添加任何新内容,因此派生类的析构函数只调用基类的析构函数。继续偏执,无论如何都要小心。
If you never allocate this class variables on heap (and it's typical to allocate vector variables on stack and as members of other classes) the non-virtual destructor problem doesn't affect you.
如果您从未在堆上分配此类变量(并且通常在堆栈上分配向量变量并作为其他类的成员),则非虚拟析构函数问题不会影响您。
回答by Zack Yezek
It can be done with a MACRO, if you're willing to push your compiler to its limits. I did it while implementing C++ equivalents for Java's "Future" and "Callable" classes. Our library uses reference-counted objects, so "Reference<T>" is itself a template class where "T" derives from "ReferencedObject".
如果您愿意将编译器推向极限,则可以使用 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>>
The beauty of this is that is that the Macro does exactly what you'd want from a "template typedef", the downsides being that you can't use "<>" for your type parameter(s) and there is no type inference.
这样做的好处在于,宏完全按照“模板 typedef”执行您想要的操作,缺点是您不能对类型参数使用“<>”并且没有类型推断.
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) { .... }