A question on variable declarations/initializations

A

Andreas Wachowski

Hi,

consider the following program:

// --------------
class A
{
public:
A(int i) { }
};

class B
{
public:
B(const A&) { }
void f(int) const { }
};

int main()
{
int i(1);

// Declaring a variable v of type B, initialized with A(i):
B v(A(i)); // Nope, this is not producing the intended behaviour, see
error messages below
// Working alternatives:
// 1) B v((A)(i));
// 2) B v(i);
// 3) B v(1);
// 4) B v = B(A(i));

v.f(i); // Sun Workshop 5.2: B(*)(A) is not a structure type
// GCC 3.3.1: request for member b in b(A), which
// is of non-aggregate type B()(A)

return 0;
}

// --------------

As far as I understand, "B v(A(i));" is interpreted as a "pointer v to a
function taking a parameter of type A and returning B". In that case,
naturally, f cannot be called on v.

I don't understand, however, why "B v(A(i));" shouldn't equally well be seen
as "variable v of type B, initialized with the temporary A(i)". For example,
what's the difference to alternative 1), "B v((A)(i));" ?

Do I miss something trivial? I would appreciate if someone could elaborate
in detail on how this declaration is interpreted.

Many thanks,
Andreas
 
G

Gianni Mariani

Andreas said:
Hi,

consider the following program:

// --------------
class A
{
public:
A(int i) { }
};

class B
{
public:
B(const A&) { }
void f(int) const { }
};

int main()
{
int i(1);

// Declaring a variable v of type B, initialized with A(i):
B v(A(i)); // Nope, this is not producing the intended behaviour, see
error messages below
// Working alternatives:
// 1) B v((A)(i));
// 2) B v(i);
// 3) B v(1);
// 4) B v = B(A(i));

v.f(i); // Sun Workshop 5.2: B(*)(A) is not a structure type
// GCC 3.3.1: request for member b in b(A), which
// is of non-aggregate type B()(A)

return 0;
}

// --------------

As far as I understand, "B v(A(i));" is interpreted as a "pointer v to a
function taking a parameter of type A and returning B". In that case,
naturally, f cannot be called on v.

I don't understand, however, why "B v(A(i));" shouldn't equally well be seen
as "variable v of type B, initialized with the temporary A(i)". For example,
what's the difference to alternative 1), "B v((A)(i));" ?

Do I miss something trivial? I would appreciate if someone could elaborate
in detail on how this declaration is interpreted.

For whatever reason, v is being interpeted as a function declaration
returning a B.

error from gcc:
request for member `f' in `v', which is of non-class type `B ()(A)'

Comeau gives a similar error.

The interesting thing is that this also works as you expect:

B v(A(1));

I don't understand how A(i) can be considered a type and not an
expression, or even that A(1) is an expression not when A(i) is not.
Also given that 3 compilers all seem to agree, I am a bit perplexed.
 
R

Rolf Magnus

Gianni said:
For whatever reason, v is being interpeted as a function declaration
returning a B.

error from gcc:
request for member `f' in `v', which is of non-class type `B
()(A)'

Comeau gives a similar error.

The interesting thing is that this also works as you expect:

B v(A(1));

I don't understand how A(i) can be considered a type and not an
expression,

B v(A(i)) declares a funcion named v that takes as a parameter named i
an object of type A and returns an object of type B. It's equivalent
to:

B v(A i)
or even that A(1) is an expression not when A(i) is not.

1 can't be the name of a parameter, but i can.
 
A

Andreas Wachowski

[snip]
B v(A(i)) declares a funcion named v that takes as a parameter named i
an object of type A and returns an object of type B. It's equivalent
to:

B v(A i)

So far, so good; thanks for the answer. I am still surprised, though, I
don't think I have seen this before. Can someone point me to a section in
the standard (or some book or other source) explaining this, perhaps? How
can one know (i.e. without relying on the compiler's error message) that the
statement "B v(A(i))" will not declare an element v of type B, initialized
with A(i)?

Your help is appreciated!

Thanks in advance, Andreas
 
R

Ron Natalie

Andreas Wachowski said:
So far, so good; thanks for the answer. I am still surprised, though, I
don't think I have seen this before. Can someone point me to a section in
the standard (or some book or other source) explaining this, perhaps? How
can one know (i.e. without relying on the compiler's error message) that the
statement "B v(A(i))" will not declare an element v of type B, initialized
with A(i)?
It's amplified in section 8.2 of the standard (Ambiguity Resolution). The rule
that when there is an ambiguity between a declaration and an expression, the
declaration wins out.

The ambiguity is if A(i) is a declaration of the parameter i of type A, or a cast
expression A(i), it is resolved as the declaration.

-Ron
 
J

jeffc

Ron Natalie said:
It's amplified in section 8.2 of the standard (Ambiguity Resolution). The rule
that when there is an ambiguity between a declaration and an expression, the
declaration wins out.

The ambiguity is if A(i) is a declaration of the parameter i of type A, or a cast
expression A(i), it is resolved as the declaration.

It never even occured to me this could be ambiguous, because I didn't know
you could declare parameters this way. Am I missing something basic, or
obscure?
 
R

Rolf Magnus

jeffc said:
It never even occured to me this could be ambiguous, because I didn't
know you could declare parameters this way. Am I missing something
basic, or obscure?

You're missing that if you declare something like:

A (i);

the parens are superfluous and ignored.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top