Fre*_*Foo 10 c++ templates destructor
我想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
}
Run Code Online (Sandbox Code Playgroud)
虽然它在Mac OS X v10.5 g++
(i686-apple-darwin10-gcc-4.2.1
)上失败了
expected class-name before ‘(’ token
Run Code Online (Sandbox Code Playgroud)
如果我改成它
obj->v.~vector<T>();
Run Code Online (Sandbox Code Playgroud)
代码无法用G ++编译,但Clang仍然可以处理它.哪个是正确的成语?在这方面是否已知这些编译器中的任何一个?
更新:定义VectorOwner
是
template <typename T>
struct VectorOwner {
PyObject_HEAD
std::vector<T> v;
};
Run Code Online (Sandbox Code Playgroud)
这是一个必须保持std::vector
活着的Python对象.我承认构造稍有危险的,但我需要的压缩存储,摊销O(1)push_back
和窃取另一个向量的内容与能力的swap
成员.
我的第一个答案实际上是错误的,litb 为我指明了正确的方向。正确的答案是\n两种语法都是正确的:
\n显式析构函数调用的语法描述于12.4 Destructors
:
12 In an explicit destructor call, the destructor name appears\n as a \xcb\x9c followed by a type-name that names the destructor\xe2\x80\x99s \n class type. The invocation of a destructor is subject to the\n usual rules for member functions (9.3) [...]\n
Run Code Online (Sandbox Code Playgroud)\ntype-name
可以在7.1.5.2 Simple type specifiers
:
type-name:\n class-name\n enum-name\n typedef-name\n
Run Code Online (Sandbox Code Playgroud)\nclass-name
描述于9. Classes
:
class-name:\n identifier\n template-id\n \n
Run Code Online (Sandbox Code Playgroud)\n因此,析构函数调用被简化为以下之一
\nfoo.~typedef-name ()\nfoo.~identifier ()\nfoo.~template-id ()\n
Run Code Online (Sandbox Code Playgroud)\n我们这里既没有 typedef-name,也没有简单的标识符,所以只有foo.~template-id()
下\n给我们了。
我们还发现在14. Templates
3 After name lookup (3.4) finds that a name is a template-name,\n if this name is followed by a <, the < is always taken as the\n beginning of a template-argument-list and never as a name\n followed by the less-than operator.\n \n
Run Code Online (Sandbox Code Playgroud)\n所以编译器必须在你的例子中假设<
模板参数列表的开头。
另外,如果你的析构函数是一个模板(...),那么
\n4 When the name of a member template specialization appears \n after . or -> in a postfix-expression, or after nested-name-specifier\n in a qualified-id, and the postfix-expression or qualified-id explicitly\n depends on a template-parameter (14.6.2), the member template name must\n be prefixed by the keyword template. Otherwise the name is assumed to \n name a non-template.\n
Run Code Online (Sandbox Code Playgroud)\n所以因为你没有在析构函数调用前f.~foo<int>
加上模板,即\nlikef.template ~foo<int>
,所以编译器必须假设您的析构函数\n 不是模板。
更远,
\n6 A template-id that names a class template specialization\n is a class-name (clause 9).\n
Run Code Online (Sandbox Code Playgroud)\n因此~foo<int>
命名您的模板专业化foo<int>
,因此是 a class-name
,\naclass-name
遵循语法规则 a type-name
,并且 a~
后跟 atypename
is\na 析构函数调用。所以
foo<int> f;\nf.~foo<int>(); // valid\n
Run Code Online (Sandbox Code Playgroud)\n但是也
\nf.~foo(); // valid\n
Run Code Online (Sandbox Code Playgroud)\n因为3.4.5 Class member access
:
3 If the unqualified-id is \xcb\x9ctype-name, and the type of the object expression\n is of a class type C (or of pointer to a class type C), the type-name is\n looked up in the context of the entire postfix-expression and in the scope of\n class C. [...]\n \n
Run Code Online (Sandbox Code Playgroud)\n因此 f.~foo();
,在 中foo
,在 内查找f.
,并且在的范围内foo<int>
,仅用 with 引用它是有效的\nfoo
。
最后,14.3 包含一劳永逸的权限:
\n5 An explicit destructor call (12.4) for an object that \n has a type that is a class template specialization may\n explicitly specify the template-arguments. [Example:\n\n template<class T> struct A {\n \xcb\x9cA();\n };\n void f(A<int>* p, A<int>* q) {\n p->A<int>::\xcb\x9cA(); // OK: destructor call\n q->A<int>::\xcb\x9cA<int>(); // OK: destructor call\n }\n\n \xe2\x80\x94end example]\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
2645 次 |
最近记录: |