Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

3.4.5: qualified pseudodestructor call lookup rules fail

0 views
Skip to first unread message

Krzysztof Żelechowski

unread,
Jan 24, 2006, 10:42:18 AM1/24/06
to
Please explain whether the following code is ill-formed:

typedef char T;

void fun(T &p_t) {
p_t.T::~T();
}

Comeau C/C++ 4.3.3 (Aug 6 2003 15:13:37) for ONLINE_EVALUATION_BETA1
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++

In strict mode, with -tused, Compile succeeded

My reasoning goes as follows:
We have to lookup for T in the context of p_t.T by 3.4.3/5 . We have the
following choices by 3.4.5:
1. p_t is not of class type. N/A.
2. p_t is not of class type and is not a pointer to a scalar type. N/A.
3. T is not preceded by ~ and T::~T is qualified. N/A.
4. If T is a class-name-or-namespace-name. How can we tell? We have to
look it up to know what it is. It is a circular definition.
Assuming we could use some fixpoint logic to resolve this, there is no way
for T to be one. N/A.
5. T is not preceded by ::. N/A.
6. T is not followed by <. N/A.
7. T is not preceded by operator keyword (BTW a link to 12.3.2 is needed
here). N/A.
I am stuck.


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

william....@gmail.com

unread,
Jan 26, 2006, 12:23:43 PM1/26/06
to
"Krzysztof Żelechowski" wrote:
> Please explain whether the following code is ill-formed:
>
> typedef char T;
>
> void fun(T &p_t) {
> p_t.T::~T();
> }
>
> My reasoning goes as follows:
> We have to lookup for T in the context of p_t.T by 3.4.3/5 . We have the
> following choices by 3.4.5:
> 1. p_t is not of class type. N/A.
> 2. p_t is not of class type and is not a pointer to a scalar type. N/A.
> 3. T is not preceded by ~ and T::~T is qualified. N/A.
> 4. If T is a class-name-or-namespace-name. How can we tell? We have to
> look it up to know what it is. It is a circular definition.
> Assuming we could use some fixpoint logic to resolve this, there is no way
> for T to be one. N/A.
> 5. T is not preceded by ::. N/A.
> 6. T is not followed by <. N/A.
> 7. T is not preceded by operator keyword (BTW a link to 12.3.2 is needed
> here). N/A.
> I am stuck.

The intent is that T in this example is looked up by an ordinary
lexical-scope lookup in the context of the complete postfix-expression.
However, you are right that the Standard does not contain a coherent
description of how this case (as well as a number of others with
respect to destructor and pseudo-destructor name lookup) is to be
handled. (See core language issues 244, 305, and 399, in particular.)

I'll open another issue for this case. Thanks for pointing it out.

-- William M. (Mike) Miller
Edison Design Group

Krzysztof Zelechowski

unread,
Jan 27, 2006, 10:39:14 AM1/27/06
to
Suppose I have the following declaration:

void do_call_destructor(A::B &x);

How should I define it to call the destructor of x, irrelevant of what A and
B is?

The obvious and the simplest solution would be to call x.~B() but it is
ill-formed if A::B resolves to a scalar type.
If I call x.A::B::~B(), do I miss the virtual destructor?
Can I
typedef A::B AB; x.~AB()?
Is it the only possible choice?

And why is it forbidden to do argument-dependent lookup for x.~B()? I think
x.~B() should be looked up like destroy(x), that is, members of B should not
be taken into account at all.
If B::B() is not allowed, why is b.B::~B()?
Chris

Uzytkownik <william....@gmail.com> napisal w wiadomosci
news:1138290832....@g43g2000cwa.googlegroups.com...

Alf P. Steinbach

unread,
Jan 27, 2006, 11:33:24 AM1/27/06
to
* Krzysztof Zelechowski:

> Suppose I have the following declaration:
>
> void do_call_destructor(A::B &x);
>
> How should I define it to call the destructor of x, irrelevant of what A and
> B is?

x.~B();

is accepted by Comeau Online; the standard is less than clear on where
qualification of B is necessary and/or disallowed; one would hope that
the infamous SomeOne (TM) would fix the standard's wording, or at least
put in some references in 12.4, to where elsewhere this is discussed.



> The obvious and the simplest solution would be to call x.~B() but it is
> ill-formed if A::B resolves to a scalar type.

Huh?


> If I call x.A::B::~B(), do I miss the virtual destructor?

You can't do that, the extra qualification is not allowed, according to
Comeau Online. But again I'm not sure where in the standard it says so.
Would be nice with a more clear wording where you don't have to be a
super-detective to ferret out the relevant details.

If you call

x.B::~B()

you're calling the destructor non-virtually, same as with any other
member function.


> Can I
> typedef A::B AB; x.~AB()?

Yes.


> Is it the only possible choice?

No.


> And why is it forbidden to do argument-dependent lookup for x.~B()?

Huh?


> I think
> x.~B() should be looked up like destroy(x), that is, members of B should not
> be taken into account at all.
> If B::B() is not allowed,

Huh?


> why is b.B::~B()?

That's a mystery; a qualified destructor call is not very meaningful.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Krzysztof Żelechowski

unread,
Jan 27, 2006, 1:26:35 PM1/27/06
to

Użytkownik "Alf P. Steinbach" <al...@start.no> napisał w wiadomości
news:43da4092....@news.individual.net...

>* Krzysztof Zelechowski:
>> Suppose I have the following declaration:
>>
>> void do_call_destructor(A::B &x);
>>
>> How should I define it to call the destructor of x, irrelevant of what A
>> and
>> B is?
>
> x.~B();
>
> is accepted by Comeau Online; the standard is less than clear on where
> qualification of B is necessary and/or disallowed; one would hope that
> the infamous SomeOne (TM) would fix the standard's wording, or at least
> put in some references in 12.4, to where elsewhere this is discussed.
>
>
>
>> The obvious and the simplest solution would be to call x.~B() but it is
>> ill-formed if A::B resolves to a scalar type.
>
> Huh?
>

Because B is looked up in the context of the calling expression, which means
it is not found.

>
>> If I call x.A::B::~B(), do I miss the virtual destructor?
>
> You can't do that, the extra qualification is not allowed, according to
> Comeau Online. But again I'm not sure where in the standard it says so.
> Would be nice with a more clear wording where you don't have to be a
> super-detective to ferret out the relevant details.

Surprise: it is the only form Microsoft Visual C++ 8 accepts. That makes
the code dramatically unportable.

>
> If you call
>
> x.B::~B()
>
> you're calling the destructor non-virtually, same as with any other
> member function.
>
>
>> Can I
>> typedef A::B AB; x.~AB()?
>
> Yes.
>
>
>> Is it the only possible choice?
>
> No.
>
>
>> And why is it forbidden to do argument-dependent lookup for x.~B()?
>
> Huh?
>
>
>> I think
>> x.~B() should be looked up like destroy(x), that is, members of B should
>> not
>> be taken into account at all.
>> If B::B() is not allowed,
>
> Huh?
>

I mean, you cannot write B::B() when B is a scalar type.

>
>> why is b.B::~B()?
>
> That's a mystery; a qualified destructor call is not very meaningful.
>

I guess that has something to do with virtuality but I am not sure.

Chris

0 new messages