c – 模板化语境中的显式析构函数

c – 模板化语境中的显式析构函数,第1张

概述我想在模板化的上下文中显式地销毁一个向量.以下为我工作(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 omitte 我想在模板化的上下文中显式地销毁一个向量.以下为我工作(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.4析构函数中描述了一个显式析构函数调用的语法:

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]
总结

以上是内存溢出为你收集整理的c – 模板化语境中的显式析构函数全部内容,希望文章能够帮你解决c – 模板化语境中的显式析构函数所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1249998.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存