By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,734 Members | 832 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,734 IT Pros & Developers. It's quick & easy.

Variable declaration or function prototype

P: n/a
Hi All,
Could someone please tell me why this code does not compile.

struct A {};

struct B {
B(A &) {}
};

struct C {
C(B &) {}
void f() {}
};

void foo() {
A a;
C c(B(a));
c.f();
}

If I change foo() to the following then it does compile:

void foo() {
A a;
B b(a);
C c(b);
c.f();
}

I would have thought that you could pass the B temporary into C's
constructor like that?

Andy
Jul 19 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Andrew Ward wrote:
Hi All,
Could someone please tell me why this code does not compile.

struct A {};

struct B {
B(A &) {}
};

struct C {
C(B &) {}
void f() {}
};

void foo() {
A a;
C c(B(a));
c.f();
}

If I change foo() to the following then it does compile:

void foo() {
A a;
B b(a);
C c(b);
c.f();
}

I would have thought that you could pass the B temporary into C's
constructor like that?


You could if you did write the constructors properly:

B(A const &);

C(B const &);

Temporaries cannot be bound to non-const references.

--
WW aka Attila
Jul 19 '05 #2

P: n/a
Andrew Ward wrote:
Hi All,
Could someone please tell me why this code does not compile.


Unless I'm mistaken, the statement

C c(B(a));

is a function declaration (prototype). It declares a function named 'c'
that is passed (by value) a class B object, and returns (by value) a
class C object. This statement does not instantiate a class C object
named 'c'.

--
Jim

To reply by email, remove "link" and change "now.here" to "yahoo"
jfischer_link5809{at}now.here.com
Jul 19 '05 #3

P: n/a

"White Wolf" <wo***@freemail.hu> wrote in message
news:bj**********@phys-news1.kolumbus.fi...
Andrew Ward wrote:
Hi All,
Could someone please tell me why this code does not compile.

struct A {};

struct B {
B(A &) {}
};

struct C {
C(B &) {}
void f() {}
};

void foo() {
A a;
C c(B(a));
c.f();
}

If I change foo() to the following then it does compile:

void foo() {
A a;
B b(a);
C c(b);
c.f();
}

I would have thought that you could pass the B temporary into C's
constructor like that?


You could if you did write the constructors properly:

B(A const &);

C(B const &);

Temporaries cannot be bound to non-const references.

--
WW aka Attila


Even when I try passing by const & like you suggested it still does not
work, the error message is:

error C2228: left of '.f' must have class/struct/union type
type is 'overloaded-function'

Maybe Jim Fischer's suggestion is correct?

Andy
Jul 19 '05 #4

P: n/a
Andrew Ward wrote:
"White Wolf" <wo***@freemail.hu> wrote in message
news:bj**********@phys-news1.kolumbus.fi...
Andrew Ward wrote:
Hi All,
Could someone please tell me why this code does not compile.

struct A {};

struct B {
B(A &) {}
};

struct C {
C(B &) {}
void f() {}
};

void foo() {
A a;
C c(B(a));
c.f();
}

If I change foo() to the following then it does compile:

void foo() {
A a;
B b(a);
C c(b);
c.f();
}

I would have thought that you could pass the B temporary into C's
constructor like that?


You could if you did write the constructors properly:

B(A const &);

C(B const &);

Temporaries cannot be bound to non-const references.

--
WW aka Attila

Even when I try passing by const & like you suggested it still does not
work, the error message is:

error C2228: left of '.f' must have class/struct/union type
type is 'overloaded-function'

Maybe Jim Fischer's suggestion is correct?


In fact, they are both correct (I think). Attila's answer is what I
would have said. The problem Jim pointed out is a bit more insidious:

C c(B(a));

I don't know the exact rule, but basically because this *could* be
either a function declaration or an object instantiation, the former
wins. It's equivalent to

C c(B a);

With a pair of superfluous parenthesis.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #5

P: n/a
Kevin Goodsell wrote:
Maybe Jim Fischer's suggestion is correct?


In fact, they are both correct (I think). Attila's answer is what I
would have said. The problem Jim pointed out is a bit more insidious:

C c(B(a));

I don't know the exact rule, but basically because this *could* be
either a function declaration or an object instantiation, the former
wins. It's equivalent to

C c(B a);

With a pair of superfluous parenthesis.


I'm 99.999% sure the statement 'C c(B(a));' is a function declaration
(see: 8.2/1 in ISO 14882:1998).

FWIW, you can disambiguate the interior subexpression 'B(a)' by wrapping
it in parens, e.g.,

C c( (B(a)) );

Now the compiler treats 'B(a)' as an object declaration that uses a
function-style type cast as the initializer (and not a function
declaration with a redundant set of parens around a parameter name).
IOW, 'B(a)' is now considered an invocation of B::B(A&). Consequently,
the surrounding expression - i.e., the declaration of 'c' - is also
treated as an object declaration with a function-style type cast as the
initializer.

Caveat: Making this change to your code introduces another problem.
Specifically, the unnamed, temporary class B object that results from
the invocation of B::B(A&) cannot be bound to a non-const reference. So
the construction of 'c' cannot occur because class C does not have a
suitable constructor - e.g., C::C(B&) cannot be used because B& is a
non-const reference. There are (at least) two fixes for this problem:

1) Modify the existing class C ctor

C(B &) { }

so its reference is const-valued

C(const B &) { }

or,

2) Add a second ctor to class C; one with a suitable const reference
argument:

class C {
C (B &) { }
C (const B &) { }
void f () { }
}

--
Jim

To reply by email, remove "link" and change "now.here" to "yahoo"
jfischer_link5809{at}now.here.com
Jul 19 '05 #6

P: n/a
Andrew Ward wrote:
[SNIP]
Even when I try passing by const & like you suggested it still does
not work, the error message is:

error C2228: left of '.f' must have class/struct/union type
type is 'overloaded-function'

Maybe Jim Fischer's suggestion is correct?


Not maybe. :-) Definitely. I am ashamed not seeing it - especially because
I have got my copy - of the book mentioning this "gotcha" - signed by the
author. Well, well well. Time for me to look for a job where no brains are
required. :-)

--
WW aka Attila
Jul 19 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.