gpt4 book ai didi

c++ - 模板化上下文中的显式析构函数

转载 作者:可可西里 更新时间:2023-11-01 16:13:04 25 4
gpt4 key购买 nike

我想在模板上下文中显式销毁一个vector。以下适用于我(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 以及使用 swap 成员窃取另一个 vector 内容的能力。

最佳答案

实际上我的第一个答案是错误的,litb 为我指明了正确的方向。正确答案是两种语法都是正确的:


析构函数调用语法。

12.4 Destructors 中描述了显式析构函数调用的语法。 :

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) [...]

type-name可以在 7.1.5.2 Simple type specifiers 中找到:

type-name:
class-name
enum-name
typedef-name

class-name9. Classes 中描述:

class-name:
identifier
template-id

因此,析构函数调用简化为以下之一

foo.~typedef-name ()
foo.~identifier ()
foo.~template-id ()

我们这里既没有 typedef-name,也没有简单的标识符,所以只有 foo.~template-id()离开了对我们来说。


编译器对带有模板参数的析构函数调用的假设。

我们还在 14. Templates 中找到

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>因此是 class-name ,一个class-name是语法规则 a type-name , 和一个 ~其次是 typename是析构函数调用。因此

foo<int> f;
f.~foo<int>(); // valid

没有模板参数的析构函数调用。

还有

f.~foo(); // valid

因为 3.4.5 Class member access :

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(); , foof. 内查找, 并且 foo<int> 的范围内, 是有效的用 foo 来引用它.


标准实际上对这个主题很明确,d'oh。

最后,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++ - 模板化上下文中的显式析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6845779/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com