问题
I have the following:
template <typename X> struct A {
typedef X _X;
};
template <typename Y> struct B { // Y is struct A
typename Y::_X x;
void call_destructor () {
x.~Y::_X(); // This doesn't work
x.Y::~_X(); // This as well
}
};
which doesn't compile, saying that
qualified type does not match destructor name
Using the keyword typename
before the call also does not work. However, the following does compile:
template <typename Y> struct B {
typename Y::_X x;
typedef typename Y::_X __X;
void call_destructor () {
x.~__X(); // This works
}
};
Can someone explain to me why, and is there any way to make do without the typedef
?
回答1:
x.~Y::_X(); // This doesn't work
Is a syntax error, I believe the compiler parses it as calling _X
in ~Y
In the second case, when you call a destructor† containing ::
, the last two type names must denote the same type
s.A::~B();
where A
and B
must be the same type. A
and B
are both looked up in the scope specified by previous specifiers, if any
x._X::~_X(); // error, can't find _X in current scope
The logical fix would be
x.Y::_X::~_X(); // error, _X is dependent name
x.typename Y::_X::~_X(); // error, typename cannot be here
Since Y::_X
is a dependent name, typename
is required to disambiguate it as a type, but the grammar of destructors doesn't admit a typename
within the expression. The end result is you must use a type alias
using X = typename Y::_X;
x.~X();
On the other hand the easiest way to write-and-forget a destructor call is simply
x.~decltype(x)();
but gcc and msvc fails to compile this.
† More precisely, a pseudo-destructor call
回答2:
You should call the destructor differently using
x.Y::_X::~_X()
The following compile fine for me:
template <typename X> struct A {
typedef X _X;
};
template <typename Y> struct B { // Y is struct A
typename Y::_X x;
void call_destructor () {
x.Y::_X::~_X(); // This as well
}
};
int main(){
B<A<int> > b;
b.call_destructor();
}
来源:https://stackoverflow.com/questions/45873952/c-explicitly-call-destructor-of-template-parameters-typedef