Re: What does "Foo( Bar() );" mean ?
On Feb 25, 9:43 pm, "Wojtek Sarzynski" <sarzyn...@gazeta.pl> wrote:
=======
Hi, I've read about "Foo x( Bar() );" in C++ FAQ LITE, section
10.19http://www.parashift.com/c++-faq-lite/ctors.html
And then I've played with similar "Foo( Bar() );" construct.
My question is: what does "Foo( Bar() )" really mean ??
See comments for details.
=======
// compiled and tested using gcc 4.1.2
#include <iostream>
using namespace std;
struct Bar
{
Bar() { cout << "Bar::Bar()" << endl; }
};
struct Foo
{
Foo(const Bar&) { cout << "Foo::Foo(const Bar&)" << endl; }
~Foo() { cout << "Foo::~Foo()" << endl; }
};
int main()
{
// doesn't call Foo constr - it declares "foo" as a function
Foo foo( Bar() );
Right. "Bar()" is interpreted as if you'd written "Bar (*)()".
// when You uncomment the following line,
// You'll get a link error: undefined reference to `Bar()'
// You don't get this error when the rest of main() is commented out
// Foo( Bar() );
This line is exactly the same as:
extern Foo Bar() ;
it declares an external function (named Bar) taking no
arguments, and returning a Foo. (I'm not sure why you'd get an
error when linking, however. Normally, unless the fucntion is
used, you won't get an error.)
Note that within an expression, Foo( Bar() ) has a completely
different meaning: it is two nested "explicit type conversions
(functional notation)". Roughly speaking (in non-standardese),
the sub-expression "Bar()" creates a temporary of type Bar,
which is then converted into a temporary of type "Foo". And
anything you do which makes the external function declaration
impossible will change the meaning, e.g.:
0, Foo( Bar() ) ;
or
(Foo( Bar() )) ;
You can also write the type conversion differently:
(Foo)( Bar() ) ;
or
static_cast< Foo >( Bar() ) ;
All of the four preceding statements have exactly the same
semantics.
// calls Foo constr and then f, gives a warning: "taking address
of temporary"
& Foo( Bar() );
Right. Because a declaration cannot begin with a &.
Note that if you uncomment the declaration above, this uses the
function Bar() (whose declaration hides the classname), rather
than a temporary of type Bar. (And bingo, a link error.)
// the same line as before, but here it's accepted by the compiler
// it still doesn't call Foo constr, though
Foo( Bar() );
The scope of a declaration only starts at the declaration; it
doesn't extend backwards. Putting the function declaration here
doesn't affect the preceding statement, so the Bar() in that
statement still signifies the classname declared at global
scope.
// gives a warning: "statement has no effect"
// - so "Foo( Bar() );" should be a STATEMENT too
int( double() );
"double" is a keyword. You can't declare a function named
"double", so this statement cannot be a function declaration.
Since it can't be a function declaration, it is an expression:
you create a temporary double (with the value 0.0), which you
convert into an int. Since the compiler can see that there are
no side effects, it gives a warning.
You can have lots of fun with this sort of thing. Put a
typedef double Double ;
before main, and:
int ( Double() ) ;
is still a function declaration (because Double is a user
defined symbol, with scope, and can be declared in a nested
scope), even if it sure looks like it should mean the same thing
as your statement.
return 0;
}
The whole declaration syntax of C (and thus of C++) is broken; I
think it was Stroustrup who refered to it as "an experiment
which failed". (Someone did, anyway, although I could be wrong
in my attribution.) It's the price we have to pay for
compatibility.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]