定义用于每个指针向量的专门化,仅用于 指针的向量,我们需要部分专业化:
template <class T> class Vector <T *> : private Vector<void *> {
public:
typedef Vector<void*> Base;
Vector(): Base() {}
explicit Vector(int i) : Base(i ) {}
T *& elem(int i ) { return static_cast <T *&> (Base::elem(i)); }
T *& opeator[](int i) { return static_cast <T *&>(Base::operator[](i )); }
//...
};
这个定义让我头晕目眩。这与部分特化有关,但我不理解语法。 private Vector<void *>
定义部分看起来像是我的父类。
Vector <void *>
中指定template <class T> class Vector <void *>
。答案 0 :(得分:2)
忘记继承,这与手头的问题毫无关系。
部分特化意味着您通过匹配更具限制性的模式,从现有的模板中创建一个更专业但仍然是通用的新模板。您的示例的一般模式是这样的:
template <typename T> class Foo; // primary template
template <typename U> class Foo<U*>; // partial specialization
template <> class Foo<fool>; // full specialization
第一行是主要模板,并匹配所有,而不是更专业的表单。第三行定义了一个实际的类型(不是模板!)Foo<fool>
(对于某些给定类型fool
)。另一方面,中间线仍然是模板,但它只匹配T = U *
形式的类型,即指针:
Foo<char> x; // uses primary template with T = char
Foo<fool> y; // uses full specialization (nothing to be matched)
Foo<int*> z; // uses partial specialization, matching U = int
关于Vector<void*>
:事实证明,作者选择将部分专用的Vector<U*>
定义为派生自固定类Vector<void*>
(必须在其他地方完全专业化) )。
答案 1 :(得分:0)
你的问题是模板专业化,这就是这里发生的事情。
这是专门用于指针类型T的Vector<T>
的模板类定义。可能,您已在其他地方定义了Vector<T>
模板,因此此代码仅针对其中的情况进行了专门化T是一个指针。因此Vector<T*>
。
由于它是一种特殊化,Vector<T*>
派生自Vector'base-template',它是Vector<void *>
。其他代码(在您的示例中未详细说明)将处理使用指针类型作为包含数据的细节。
答案 2 :(得分:0)
基本上,这使得任何指针类型的Vector<Ptr>
成员转发到Vector<void*>
(使用继承和显式基本调用加上转换的组合)。这可以防止编译器生成相同代码的许多相同版本,只有指针类型不同,可能在最终可执行文件中节省空间(尽管大多数链接器足够智能组合相同的函数,例如参见“COMDAT折叠”)
根据标准,这是有问题的,因为指针没有相同的对齐限制。并非所有对象指针在一致的实现中都必须具有相同的大小。事实上,我很惊讶编译器完全接受static_cast<T*&>(a_void_ptr)
。当然允许在void*
和T*
之间进行静态转换,但这会处理与引用无关的引用类型。它应该需要reinterpret_cast
。
答案 3 :(得分:0)
似乎代码的作者想要利用不同指针类型的代码相同的事实。减少代码大小或“代码膨胀”可能只是一个不成熟的优化。这个想法很可能是每个新的指针类型只会向void指针代码添加一层static_cast。