加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 05:47:23 所属栏目:百科 来源:网络整理
导读:我想在模板化的上下文中显式地销毁一个向量.以下为我工作(GNU C 4.3,4.4和Clang 1.1): template typename Tvoid destroy_vector_owner(VectorOwnerT *obj){ obj-v.~vector(); // further cleanup by Python API functions omitted} 而在Mac OS X v10.5的g(i
我想在模板化的上下文中显式地销毁一个向量.以下为我工作(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]

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读