C++ 模板化上下文中的显式析构函数
我想在模板化上下文中显式销毁C++ 模板化上下文中的显式析构函数,c++,templates,destructor,C++,Templates,Destructor,我想在模板化上下文中显式销毁向量。下面的工作为我(GNU C++ 4.3,4.4和CLAN+++):< /P> 如果我把它改成 obj->v.~vector<T>(); 这是一个Python对象,它必须使std::vector保持活动状态。我承认这个构造有点危险,但我需要紧凑的存储,分期偿还的O(1)push_,以及使用swap成员窃取另一个向量的内容的能力。来自n3290,3.4.5类成员访问[basic.lookup.classref] 3如果非限定id为~type na
向量。下面的工作为我(GNU C++ 4.3,4.4和CLAN+++):< /P>
如果我把它改成
obj->v.~vector<T>();
这是一个Python对象,它必须使std::vector
保持活动状态。我承认这个构造有点危险,但我需要紧凑的存储,分期偿还的O(1)push_
,以及使用swap
成员窃取另一个向量的内容的能力。来自n3290,3.4.5类成员访问[basic.lookup.classref]
3如果非限定id为~type name,则在中查找类型名称
整个后缀表达式的上下文。如果
对象表达式是C类类型,类型名称也会被查找
C类范围内的查找。至少一个查找应找到
引用(可能是cv限定的)T.[…]的名称
下面是一个示例(作为非规范性说明),其中包含以下代码片段:
a->~A(); // OK: lookup in *a finds the injected-class-name
特别是对于模板类向量
,vector
是注入的类名。因此,我相信
obj->v.~vector();
这是正确的
(我现在没有什么要说的关于~vector
。您可以尝试以下语法,它在gcc中也适用:
obj->v.template ~vector<T>();
obj->v.template~vector();
.我的第一个答案是错的实际上,利特把我的答案指向了正确的方向。正确答案是
这两种语法都是正确的:
析构函数调用语法。
显式析构函数调用的语法如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) [...]
type-name:
class-name
enum-name
typedef-name
类型名称
可在7.1.5.2简单类型说明符
中找到:
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:
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.
所以,因为您没有在析构函数调用f.~foo
前面加上模板,即。
与f.template~foo
类似,编译器必须假定您的析构函数
不是模板
回溯
此外
6 A template-id that names a class template specialization
is a class-name (clause 9).
因此,~foo
命名您的模板专门化foo
,因此是一个类名
,
根据语法规则,类名
是一个类型名
,后面跟着类型名的~
是
析构函数调用。所以
foo<int> f;
f.~foo<int>(); // 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
的范围内,它是有效的
仅使用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]
5对以下对象的显式析构函数调用(12.4)5
具有类模板专用化的类型
显式指定模板参数。[示例:
模板结构A{
~A();
};
空f(A*p,A*q){
p->A::~A();//确定:析构函数调用
q->A::«A();//确定:析构函数调用
}
-[结束示例]
你能发布矢量所有者的定义吗?你到底为什么要这样做?为什么不让对象超出范围?如果出于某种奇怪的原因,这不是一个选项,那么请使用某种智能指针,如boost::shared_ptr
或其他什么。等等,当它不是指针时,您是如何初始化obj.v
的?你是否取消引用了一个新表达式的结果?无论如何,我甚至不确定静态分配的对象是否会像这样被删除。。。这不会弄乱你的书堆吗?我明白了,很公平。看起来问题只是因为编译器的错误。(例如,您发布的两个版本都在GCC4.6.1中工作。)这确实是一个非常有趣的问题!你能补充一下“注入的名称”包括名称空间吗?@Kerrek我想这就是类范围的意思。如果这不是你的意思,请在聊天中通知我,如果你不介意的话。该代码说“亲爱的编译器,请查找模板~vector
”,但OP没有定义模板析构函数。
f.~foo(); // valid
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. [...]
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]