I want to explicitly destroy a vector in a templated context. The following works for me (GNU C++ 4.3, 4.4 and Clang++ 1.1):
template <typename T>
void destroy_vector_owner(VectorOwner<T> *obj)
{
obj->v.~vector();
// further cleanup by Python API functions omitted
}
while it fails on Mac OS X v10.5’s g++ (i686-apple-darwin10-gcc-4.2.1) with
expected class-name before ‘(’ token
If I change it to
obj->v.~vector<T>();
the code fails to compile with G++, but Clang can still handle it. Which is the correct idiom? Are any of these compilers known to be broken in this regard?
Update: the definition of VectorOwner is
template <typename T>
struct VectorOwner {
PyObject_HEAD
std::vector<T> v;
};
This is a Python object that has to keep an std::vector alive. I admit that the construct is slightly dangerous, but I need the compact storage, amortized O(1) push_back and the ability to steal another vector’s contents with the swap member.
My first answer was wrong actually, litb pointed me into the right direction. The right answer is
that both syntaxes are correct:
Destructor call syntax.
The syntax for an explicit destructor call is described in
12.4 Destructors:type-namecan be found in7.1.5.2 Simple type specifiers:class-nameis described in9. Classes:So a destructor call is, simplified, one of the following
We neither have a typedef-name here, nor a simple identifier, so only
foo.~template-id()is leftfor us.
Compiler’s assumption on destructor call with template-arguments.
We also find in
14. TemplatesSo the compiler must assume in your example that the
<is the beginningof a template-argument-list.
Also, if your destructor would be a template (…), then
So because you did not prefix your destructor call
f.~foo<int>with template, i.e.like
f.template ~foo<int>, the compiler must assume that your destructoris NOT a template.
Backtrack.
Further,
So
~foo<int>names your template specializationfoo<int>and therefore is aclass-name,a
class-nameis by the grammar rules atype-name, and a~followed by atypenameisa destructor call. Therefore
Destructor call without template-arguments.
But also
Because
3.4.5 Class member access:thus in
f.~foo();,foois looked up withinf., and within the scope offoo<int>, it is validto refer to it just with with
foo.The standard is actually explicit on this topic, d’oh.
And finally, 14.3 contains the one-and-for-all-permission: