 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Markus Guest
|
Posted: Sat Dec 20, 2003 11:52 am Post subject: typedefs and vanished code |
|
|
Could somebody PLEASE explain to me why the following code compiles (gcc 3.3):
typedef char* S;
typedef int IX;
void x(const double& s) {
IX i(S(s));
}
The original problem is a lot more complex, but after making things simpler and
simpler and sustituting real classes with arbitrary types it boils down to
the above code. In the original code the constructor of the class IX never
gets called.
Any enlightment is highly appreciated
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Andrea Griffini Guest
|
Posted: Sat Dec 20, 2003 5:37 pm Post subject: Re: typedefs and vanished code |
|
|
On 20 Dec 2003 06:52:23 -0500, [email]markuslampert (AT) yahoo (DOT) com[/email] (Markus) wrote:
| Quote: | Could somebody PLEASE explain to me why the following code compiles (gcc 3.3):
typedef char* S;
typedef int IX;
void x(const double& s) {
IX i(S(s));
}
The original problem is a lot more complex, but after making things simpler and
simpler and sustituting real classes with arbitrary types it boils down to
the above code. In the original code the constructor of the class IX never
gets called.
Any enlightment is highly appreciated
|
"Be alert for C++'s most vexing parse"
(Scott Meyers in Effective STL)
His suggestion before reading is to take a chair and sit down.
The case he analyze is more convoluted, but the problem is
the same you are facing.
The text "IX i(S(s))" can be consider as the declaration of a
function named "i", returning an "IX" and that accepts a
parameter of type "S". The "(s)" part is just the (ignored)
parameter name enclosed in (useless and ingored) parenthesis
and has no relation to the "double&" parameter received by x.
Is this horrible ? IMO Yes.
Was it really needed by C++ ? IMO No, but I don't knows all
the gory details so there may be a true explanation of why
this was the Right Thing for C++.
Having initialization that supports two different syntax to
do the same thing creates this problem; especially because
the form "IX i(...)" to declare an initialized IX instance
is very similar to the function declaration.
It's actually *more* than just similar and indeed can't be
distinguished at all; so the rule is "if it can be interpreted
as a declaration then it's a declaration, otherwise it's not".
What happens (and it's not a rare evenience) is that people
write something thinking to a definition of an initialized
object and instead is writing a prototype of a function.
This C++ rule also make the compiler to face problems much
more complex because you can have an *arbitrarely long*
sequence of tokens in which the meaning of *any* of them can't
be decided until the sequence is *complete*.
IMO C++ wouldn't have been worse allowing only the form
"IX i=IX(...)" to mean definition and initialization.
HTH
Andrea
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dhruv Guest
|
Posted: Sat Dec 20, 2003 5:43 pm Post subject: Re: typedefs and vanished code |
|
|
On Sat, 20 Dec 2003 06:52:23 -0500, Markus wrote:
| Quote: | Could somebody PLEASE explain to me why the following code compiles (gcc 3.3):
typedef char* S;
typedef int IX;
void x(const double& s) {
IX i(S(s));
}
The original problem is a lot more complex, but after making things simpler and
simpler and sustituting real classes with arbitrary types it boils down to
the above code. In the original code the constructor of the class IX never
gets called.
|
This bug has bitten many times, and I have gotten myself kind of
vaccinated against it. However some strains of it might still be
potentially harmful!!!
This statement:
IX i(S(s));
Actually declares a function 'i' that returns an int, and takes a char*
parameter named 's'. That's really amusing...
Regards,
-Dhruv.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Sat Dec 20, 2003 7:54 pm Post subject: Re: typedefs and vanished code |
|
|
Markus wrote:
| Quote: | typedef char* S;
typedef int IX;
void x(const double& s) {
IX i(S(s));
}
The original problem is a lot more complex, but after making things
simpler and simpler and sustituting real classes with arbitrary types
it boils down to the above code. In the original code the constructor
of the class IX never gets called.
|
Hehe, that one's a good one: the point is, you never tell the compiler to
construct an object. Instead, you declare a function called 'i', returning
an 'IX' and taking an 'S' called 's'. I think the solution is to
double-bracket the (first) parameter like this
IX i((S(s)));
The rule is that if foo can be parsed as a declaration, it is a
declaration.
Uli
--
Questions ?
see C++-FAQ Lite: http://parashift.com/c++-faq-lite/ first !
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ron Natalie Guest
|
Posted: Sat Dec 20, 2003 7:56 pm Post subject: Re: typedefs and vanished code |
|
|
"Markus" <markuslampert (AT) yahoo (DOT) com> wrote
| Quote: | Could somebody PLEASE explain to me why the following code compiles (gcc
3.3):
typedef char* S;
typedef int IX;
void x(const double& s) {
IX i(S(s));
}
The original problem is a lot more complex, but after making things
simpler and
simpler and sustituting real classes with arbitrary types it boils down to
the above code. In the original code the constructor of the class IX never
gets called.
|
The code above shows a bit of C++ syntax bizzareness. The above
declaration
is syntactically the same as:
IX i(S s) ;
You've defined a function taking an S returning an IX,
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Peter Schneider Guest
|
Posted: Sat Dec 20, 2003 7:58 pm Post subject: Re: typedefs and vanished code |
|
|
Hi Markus,
"Markus" <markuslampert (AT) yahoo (DOT) com> wrote in
news:9eefe197.0312192125.20982f38 (AT) posting (DOT) google.com...
| Quote: | Could somebody PLEASE explain to me why the following
code compiles (gcc 3.3):
typedef char* S;
typedef int IX;
void x(const double& s) {
IX i(S(s)); // [ function declaration. -ps ]
}
The original problem is a lot more complex, but after making things simpler and
simpler and sustituting real classes with arbitrary types it boils down to
the above code. In the original code the constructor of the class IX never
gets called.
|
It puzzled me too! Solution from the Standard:
"
[dcl.ambig.res] 8.2 Ambiguity resolution
1 The ambiguity arising from the similarity between a
functionstyle cast and a declaration mentioned in 6.8
can also occur in the context of a declaration. In that
context, the choice is between a function declaration
with a redundant set of parentheses around a
parameter name and an object declaration with a functionstyle
cast as the initializer. Just as for the ambiguities
mentioned in 6.8, the resolution is to consider any construct
that could possibly be a declaration a declaration.
[Note: a declaration can be explicitly disambiguated
by a nonfunctionstyle cast, by a = to indicate initialization
or by removing the redundant parentheses around the parameter name.
"
Right, "IX i((S)(s));" didn't compile,
yielding a type conversion error.
That was what made me suspicious, because the two should
be equivalent (Standard 5.2.3,1).
That function declarations often are not in a nested scope
provides an extra camouflage for this one.
Regards, Peter
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Timo Ylhainen Guest
|
Posted: Sat Dec 20, 2003 8:59 pm Post subject: Re: typedefs and vanished code |
|
|
"Markus" <markuslampert (AT) yahoo (DOT) com> wrote
| Quote: | Could somebody PLEASE explain to me why the following code compiles (gcc
3.3):
typedef char* S;
typedef int IX;
void x(const double& s) {
IX i(S(s));
}
|
As already mentioned, i(S(s)) here serves as a declaration of a function
(and 's' in paranthesis gets ignored).
Maybe this will ease the horror a bit. The following program:
typedef char* S;
typedef int IX;
void x(const double& s) {
IX i(S(s));
char *z = "something";
i(z);
}
int main()
{
x(2.0);
}
should still compile but you get a link error.
-- Timo
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Benoit Dejean Guest
|
Posted: Sun Dec 21, 2003 1:22 am Post subject: Re: typedefs and vanished code |
|
|
Le Sat, 20 Dec 2003 14:56:56 -0500, Ron Natalie a écrit :
| Quote: | typedef char* S;
typedef int IX;
void x(const double& s) {
IX i(S(s));
}
The code above shows a bit of C++ syntax bizzareness. The above
declaration
is syntactically the same as:
IX i(S s) ;
You've defined a function taking an S returning an IX,
|
of course. the standars says that when something looks like a declaration,
sounds like a declaration, tastes like a declaration, it is a declaration.
recently in the pre-kona documents BS showed another example.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jeffrey Turner Guest
|
Posted: Sun Dec 21, 2003 1:24 am Post subject: Re: typedefs and vanished code |
|
|
Ron Natalie wrote:
| Quote: | "Markus" <markuslampert (AT) yahoo (DOT) com> wrote:
Could somebody PLEASE explain to me why the following code compiles (gcc
3.3):
typedef char* S;
typedef int IX;
void x(const double& s) {
IX i(S(s));
}
The original problem is a lot more complex, but after making things
simpler and
simpler and sustituting real classes with arbitrary types it boils down to
the above code. In the original code the constructor of the class IX never
gets called.
The code above shows a bit of C++ syntax bizzareness. The above
declaration
is syntactically the same as:
IX i(S s) ;
You've defined a function taking an S returning an IX,
|
What else would it be? Anyone who uses lots of typedefs deserves to
be bitten, but is there a better explanation for what
IX i(S(s));
should declare? Casts should involve <..._cast>, no?
--Jeff
--
"I don't mind being characterized as a 'liberal'
- I just don't happen to believe it's true."
Howard Dean
A Dean supporter is just a Democrat who hasn't
listened to Kucinich.
http://www.kucinich.us/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Markus Guest
|
Posted: Sun Dec 21, 2003 1:33 am Post subject: Re: typedefs and vanished code |
|
|
Thanks everybody for restoring my sanity (although I now question the
standards ..). I didn't know that I can declare a function within a
function scope.
Anyway, the example below illustrates a bit better why I consider this
a bug in the standard. It comes down to having a lock for a specific
resource in a multithreaded application. And guess what, the code
compiles just fine, the resource never gets locked .... say hello to
classic race condition!
// ------------------ code -----------------------
#include <string>
#include <iostream>
template<typename T>
class ALock {
T t_;
public:
ALock( const T& t) :t_( t) { std::cout << t_ << std::endl; }
~ALock() { std::cout << '~' << t_ << std::endl; }
};
class AClass {
std::string name_;
public:
AClass( const std::string& name) :name_( name) {}
std::string name() const { return name_; }
};
std::ostream& operator<<( std::ostream& os, const AClass& obj) {
return os << obj.name();
}
typedef ALock
void x(const std::string& s) {
Lock lock( AClass( s));
std::cout << "trace" << std::endl;
}
int main( int, char**) {
x( "check");
return 0;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ron Natalie Guest
|
Posted: Sun Dec 21, 2003 11:43 am Post subject: Re: typedefs and vanished code |
|
|
"Jeffrey Turner" <jturner (AT) localnet (DOT) com> wrote
| Quote: | You've defined a function taking an S returning an IX,
What else would it be? Anyone who uses lots of typedefs deserves to
be bitten,
|
Typedefs don't matter here. If IX and S were class names it would behave
the same
way.
| Quote: | but is there a better explanation for what
IX i(S(s));
|
The parens around the s are syntactically discarded. It's simple as that.
| Quote: |
should declare? Casts should involve <..._cast>, no?
Who said anything about casts? S(s) might be a explicit type conversion in |
some
cases, but it isn't here.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Sun Dec 21, 2003 4:33 pm Post subject: Re: typedefs and vanished code |
|
|
In message <9eefe197.0312201357.35653e8a (AT) posting (DOT) google.com>, Markus
<markuslampert (AT) yahoo (DOT) com> writes
| Quote: | Thanks everybody for restoring my sanity (although I now question the
standards ..). I didn't know that I can declare a function within a
function scope.
Anyway, the example below illustrates a bit better why I consider this
a bug in the standard. It comes down to having a lock for a specific
resource in a multithreaded application. And guess what, the code
compiles just fine, the resource never gets locked .... say hello to
classic race condition!
|
Writing multi-threaded code is always hard work but trying to do it
without a reasonably complete understanding of the tools is a recipe for
disaster. That is not the languages fault.
BTW function declarations lexically at class scope have been around for
a very long time (and were inherited from C which is the reason that C++
had to accept them or break a great deal of legacy C)
| Quote: |
typedef ALock<AClass> Lock;
void x(const std::string& s) {
Lock lock( AClass( s));
|
Write this line as:
Lock lock(static_cast<AClass>(s));
and I think your problem goes away. Using C-style casts or the function
style C++ equivalent (conversions) is dangerous which is why the
Standard introduced a more precise set of alternatives.
This does not solve all the problems with declarations that are intended
to define a variable but actual declare a function but it certainly
cures a good number of them.
| Quote: | std::cout << "trace" << std::endl;
int main( int, char**) {
x( "check");
return 0;
|
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
or http://www.robinton.demon.co.uk
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Sun Dec 21, 2003 4:36 pm Post subject: Re: typedefs and vanished code |
|
|
In message <3fe50cff$0$70038$9a6e19ea (AT) news (DOT) newshosting.com>, Ron Natalie
<ron (AT) sensor (DOT) com> writes
| Quote: | should declare? Casts should involve <..._cast>, no?
Who said anything about casts? S(s) might be a explicit type conversion in
some
cases, but it isn't here.
|
But in the context of the original post it was intended to be and the
fact that it wasn't was the problem. I.e. if we want a type conversion
we need to say so unambiguously.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
or http://www.robinton.demon.co.uk
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Sun Dec 21, 2003 4:37 pm Post subject: Re: typedefs and vanished code |
|
|
In message <3fe50cff$0$70038$9a6e19ea (AT) news (DOT) newshosting.com>, Ron Natalie
<ron (AT) sensor (DOT) com> writes
| Quote: | Who said anything about casts? S(s) might be a explicit type conversion in
some
cases, but it isn't here.
|
But the problem was exactly that the OP had thought he was writing a
conversion (or function style cast) but wasn't. Interestingly had he
actually written a C-style cast he would have got the expected error
because;
IX i((S) s);
cannot be parsed as a function declaration.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
or http://www.robinton.demon.co.uk
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Mon Dec 22, 2003 8:37 am Post subject: Re: typedefs and vanished code |
|
|
Francis Glassborow <francis (AT) robinton (DOT) demon.co.uk> writes:
| Quote: | In message <9eefe197.0312201357.35653e8a (AT) posting (DOT) google.com>, Markus
[email]markuslampert (AT) yahoo (DOT) com[/email]> writes
Thanks everybody for restoring my sanity (although I now question the
standards ..). I didn't know that I can declare a function within a
function scope.
Anyway, the example below illustrates a bit better why I consider this
a bug in the standard. It comes down to having a lock for a specific
resource in a multithreaded application. And guess what, the code
compiles just fine, the resource never gets locked .... say hello to
classic race condition!
Writing multi-threaded code is always hard work but trying to do it
without a reasonably complete understanding of the tools is a recipe for
disaster. That is not the languages fault.
|
I think it is. The language doesn't have to have this pitfall, at
least not in priciple. Even those of us with a "reasonably complete
understanding of the tools" fall into this trap more often than we'd
care to admit.
| Quote: | BTW function declarations lexically at class scope
|
You must mean "function scope"
| Quote: | have been around for a very long time (and were inherited from C
which is the reason that C++ had to accept them or break a great
deal of legacy C)
|
True, but most well-structured programs don't use them. I keep
wondering why compiler vendors haven't given us a warning about these
things for the cases where they look like variable declarations.
| Quote: | typedef ALock<AClass> Lock;
void x(const std::string& s) {
Lock lock( AClass( s));
Write this line as:
Lock lock(static_cast<AClass>(s));
and I think your problem goes away. Using C-style casts or the function
style C++ equivalent (conversions) is dangerous which is why the
Standard introduced a more precise set of alternatives.
|
That's not really a satisfying answer either. static_cast lets you do
all kinds of dangerous things. OK, not *all* kinds, but plenty of
kinds. I know it's an extreme statement, but I think this corner of
the C++ language is a travesty. Problem:
Write a generic function taking type parameters T,U which constructs
a T from a U object, but will only compile if it's "safe" to
construct a T from a U. By "safe" I mean that the conversion
shouldn't lead to undefined behavior in a well-behaved program.
That rules out, e.g. Base->Derived and int*->long*. Write two
versions: the first should only compile if there's an implicit
conversion U->T. The second should be less-restrictive, also
compiling if there's an *explicit* constructor for T from a U
object.
If C++-style cast operators solve all the problems given by the ones
from 'C', why is this problem so hard to solve in C++?
C++ is seriously lacking implicit_cast. The best simulation I
could find is the one at
http://www.boost-consulting.com/boost/boost/implicit_cast.hpp.
Unfortunately, it's not perfect because it requires the target type to
have an accessible copy ctor. We're also lacking the explicit
version hinted at in the problem above.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|