微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

我想在模板化的上下文中显式地销毁一个向量.以下为我工作(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]

原文地址:https://www.jb51.cc/c/113761.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐