我想在模板化的上下文中显式地销毁一个向量.以下为我工作(GNU C 4.3,4.4和Clang 1.1):
template <typename T> void destroy_vector_owner(VectorOwner<T> *obj) { obj->v.~vector(); // further cleanup by Python API functions omitted }
而在Mac OS X v10.5的g(i686-apple-darwin10-gcc-4.2.1)上,它失败了
expected class-name before ‘(’ token
如果我把它改成
obj->v.~vector<T>();
代码无法用G编译,但Clang仍然可以处理它.哪个是正确的成语?这些编译器是否已知在这方面被破坏?
更新:VectorOwner的定义是
template <typename T> struct VectorOwner { PyObject_HEAD std::vector<T> v; };
这是一个Python对象,必须保持一个std :: vector.我承认构造是有点危险的,但是我需要紧凑型存储,分摊O(1)push_back,并且能够使用交换成员来窃取另一个向量的内容.
解决方法
我的第一个答案实际上是错误的,litb指出我的方向正确.正确的答案是
这两种语法都是正确的:
这两种语法都是正确的:
12 In an explicit destructor call,the destructor name appears as a ˜ followed by a type-name that names the destructor’s class type. The invocation of a destructor is subject to the usual rules for member functions (9.3) [...]
类型名称可以在7.1.5.2中找到简单类型说明符:
type-name: class-name enum-name typedef-name
类名称在9中描述.类:
class-name: identifier template-id
foo.~typedef-name () foo.~identifier () foo.~template-id ()
我们这里没有typedef名称,也没有一个简单的标识符,所以只有foo.〜template-id()留下
为了我们.
我们也在14.模板
3 After name lookup (3.4) finds that a name is a template-name,if this name is followed by a <,the < is always taken as the beginning of a template-argument-list and never as a name followed by the less-than operator.
所以编译器必须在你的例子中假定<是开始
的模板参数列表.
另外,如果你的析构函数是一个模板(…),那么
4 When the name of a member template specialization appears after . or -> in a postfix-expression,or after nested-name-specifier in a qualified-id,and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2),the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.
所以因为你没有前缀你的析构函数调用f.〜foo< int>使用模板,即
像f.template〜foo< int>,编译器必须假设你的析构函数
不是模板.
原路返回.
进一步,
6 A template-id that names a class template specialization is a class-name (clause 9).
所以〜foo< int>命名你的模板专业化foo< int>因此是一个类名,
一个类名是由语法规则的一个类型名称,一个〜后面是一个typename
一个析构函数调用.因此
foo<int> f; f.~foo<int>(); // valid
但也
f.~foo(); // valid
因为3.4.5类成员访问:
3 If the unqualified-id is ˜type-name,and the type of the object expression is of a class type C (or of pointer to a class type C),the type-name is looked up in the context of the entire postfix-expression and in the scope of class C. [...]
因此在f.〜foo(); foo在f.中查找,并且在foo< int>范围内,它是有效的
用foo来指代它.
这个标准实际上是明确的这个话题,哦.
最后,14.3包含一个全然的权限:
5 An explicit destructor call (12.4) for an object that has a type that is a class template specialization may explicitly specify the template-arguments. [Example: template<class T> struct A { ˜A(); }; void f(A<int>* p,A<int>* q) { p->A<int>::˜A(); // OK: destructor call q->A<int>::˜A<int>(); // OK: destructor call } —end example]