Re: Valid code or not?
On Jun 23, 5:21 pm, WDS <B...@seurer.net> wrote:
I was compiling some old code with a new compiler and it
flagged a statement as an error. This code compiled (and ran)
fine with an older version of the same compiler. The
following snippet demonstrates:
#include <vector>
void P()
{
std::vector<bool> p;
p.std::~vector<bool>(); // Line 6
}
It that actually valid code?
I can't tell, reading the standard. What's interesting is that
given:
namespace N {
enum E { a, b, c } ;
class C {} ;
}
int
main()
{
N::E e ;
N::C c ;
e.N::~E() ;
c.N::~C() ;
}
g++ (4.1.0) accepts the first destructor call, but not the
second. In your example, both
p.std::vector<bool>::~vector<bool>() and p.~vector<bool>() work,
but qualifying with the namespace, but not the class name,
doesn't.
This is covered in several different places in the standard, and
it seems possible as irrational as it seems, this behavior from
g++ is what the standard requires. The standard seems to
distinguish between "pseudo destructor calls" (=A75.2.4, for
non-class types) and "explicit destructor calls" (=A712.4/11, for
class types). I can't find any grammar productions for the
latter, however. All of the examples under consideration
correspond to the grammar for a pseudo destructor call, but
=A75.2.4 seem to imply that there is a semantic restriction on
this production, and that it can only be used if the type name
is not a class type. I would have imagined that the intent was
(or should have been) that the grammar for both explicit
destructor calls and pseudo destructor calls be the same, and
that only the semantics depend on whether the object is a class
type or not. (Another interesting question is if the type name
is an array of class types---an array is not a class type, even
if its elements are, and =A75.2.4 would seem to say that the
following is legal:
class C { public : ~C() ; } ;
typedef C A[5] ;
int main()
{
A a ;
a.~A() ;
}
but that the "pseudo destructor call" doesn't actually call any
destructors.)
I tried the snippet with various compilers and here's what I
found:
#1: gCC
gCC 3.3.2 accepts it but 3.4.5 complains:
t.C: In function `void P()':
t.C:6: error: `std::~std::vector<bool, std::allocator<bool> >' is not
a member of `std::vector<bool, std::allocator<bool> >'
#2: xlC
AIX xlC older versions accept it but the latest version complains:
"t.C", line 6.24: CZP0157(30) The text ">" is unexpected. It
may be that this token was intended as a template argument
list terminator but the name is not known to be a template.
#3: Visual C++
Both Microsoft Visual 2005 and 2008 C++ complain:
t.cpp(6) : error C2588: '::~vector' : illegal global destructor
Given the ambiguities in the standard, I'm not too surprised
that compilers differ, although from what you say, the evolution
seems to be in the same direction. You can always drop all
namespace qualifications for a class type; the fact that the
type to the left of the . or the -> is a class type conditions
name lookup in such a way that the code will work. If the code
is in a template, however, and you don't know whether the type
is a class type or not, you may have a problem. (On the other
hand, I can't think of a case where you wouldn't know except
when the type is an instantiation type of the template. And you
don't want a namespace qualifier there.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34