ambiguity resolution between function declaration and object declaration

50 views
Skip to first unread message

Ronny

unread,
Jun 7, 2000, 3:00:00 AM6/7/00
to
Consider the statement

T f();

This could be parsed as a variable f of type T, initialized using
the default constructor, or a function f returning a T.

I believe to remember that this ambiguity is resolved as a
function declaration, but I was not able to locate this in the
standard. Can someone point out the chapter and paragraph in the
standard which clarifies this problem?

Ronald

--
Ronald Fischer [http://profiles.yahoo.com/ronny_fischer/]
Please email me at rona...@my-deja.com, NOT at the address given
in the header, which is wrong (RemarQ does not allow to edit it).
* Sent from RemarQ http://www.remarq.com The Internet's Discussion Network *
The fastest and easiest way to search and participate in Usenet - Free!

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]


Ron Natalie

unread,
Jun 7, 2000, 3:00:00 AM6/7/00
to

Ronny wrote:
>
> Consider the statement
>
> T f();
>
> This could be parsed as a variable f of type T, initialized using
> the default constructor, or a function f returning a T.

It's not ambiguous at all. It's a declaration of a function.
Since this is a declaration, the initializer (section 8.5) can't be
an empty set of parens (to be gramatically the declaration
initailizer, it has to have expression-list inside it which
has at least one expression). This is different than the
other places you are thinking about (in new, in function-style
casts, and in the mem-initializers in constructors) which
permit the expression-list to be OMITTED.

Hyman Rosen

unread,
Jun 7, 2000, 3:00:00 AM6/7/00
to
Ronny <rona...@myremarq.com> writes:
> Consider the statement
> T f();
> This could be parsed as a variable f of type T, initialized using
> the default constructor, or a function f returning a T.
>
> I believe to remember that this ambiguity is resolved as a
> function declaration, but I was not able to locate this in the
> standard. Can someone point out the chapter and paragraph in the
> standard which clarifies this problem?

8.5/8.

Ron Hunsinger

unread,
Jun 8, 2000, 3:00:00 AM6/8/00
to
In article <01617965...@usw-ex0105-036.remarq.com>, Ronny
<rona...@myremarq.com> wrote:

> Consider the statement
>
> T f();
>
> This could be parsed as a variable f of type T, initialized using
> the default constructor, or a function f returning a T.
>
> I believe to remember that this ambiguity is resolved as a
> function declaration, but I was not able to locate this in the
> standard. Can someone point out the chapter and paragraph in the
> standard which clarifies this problem?

There are several variations of this ambiguity, and they're addressed in
the standard in the various places where it comes up. My favorite is:

8.2 Ambiguity resolution [dcl.ambig.res]
1 The ambiguity arising from the similarity between a function-style
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 function-style
cast as the initializer. Just as for the ambiguities mentioned in
6.8, the resolution is to consider any con-struct that could
possibly be a declaration a declaration.

In other words, when the ambiguity is between one type of declaration and
another type of declaration, the ambiguity is resolved in favor of
interpreting it as a declaration.

There, isn't everything clearer now?

Truth is, I'd like to see a simple (i.e., easy to remember, apply, and
explain) rule that covers all versions of this ambiguity *accurately* and
concisely. As it is, I just avoid writing anything that looks like it
might
be ambiguous. That only helps with new code, of course, and has the extra
pitfall that some of the ambiguous cases don't look ambiguous at first
blush (especially when you have one of the interpretations in mind when
you
write it).

But in your particular case, the question boils down to: is the "()" part
of that chunk of code a <parameter-list> (which would make f a function
returning T) or an <initializer> (which would make f an object of type
T).

And that, as it turns out, isn't even ambiguous in the grammar. The
applicable grammar rules are:

From 8.3.5: Functions [dcl.fct]

we see that a function declarator looks like:

D1 ( parameter-declaration-clause ) cv-qualifier-seq opt
exception-specification opt

where:

parameter-declaration-clause:
parameter-declaration-list opt ...opt
parameter-declaration-list , ...

In other words, the parameter list for a function declaration can be
empty
(by invoking the "opt" modifier on everything in the first rule).
However,

From 8.5: Initializers:

initializer:
= initializer-clause
( expression-list )

which shows, by the absence of an "opt" modifier on the expression-list,
that an empy set of parentheses NEVER forms the initializer for an
object.

In other words, if you write:

T f();

the only interpretation permitted by the grammar is that f is a function
taking no parameters and returning T. No ambiguity to be resolved. If
what
you wanted was an explicitly default-constructed object of type T, you
have
to write that as:

T f = T();

The ambiguities in the grammar apparently all come from trying to decide
between

T f( expression-list ); // f is object
T f( parameter-declaration-list ); // f is function

where it might not be clear whether something in the the list is an
expression or a parameter-declaration.

And I *think* that what the standard is trying to say is that, if
everything between parentheses could possibly be interpreted as a
parameter-declaration, then treat them all as such and declare a
function.
Otherwise, they'd better all be interpretable as expressions, and pass
them
to a suitably-chosen constructor for the object being declared. (Note
that
this wording covers the empty list also, since everything in the empty
list
can be interpreted any way you please, including as
parameter-declarations.)

What bugs me is that:

T f( T() );

can be interpreted as:

T f( T );

with some redundant parentheses, making f a function taking a T
parameter.
Say what? I'm suppose to see that without having it pointed out? When
what's "obviously" intended is to construct in f an object of type T
using
as parameter the default value of type T?

-Ron Hunsinger

Martin Fabian

unread,
Jun 8, 2000, 3:00:00 AM6/8/00
to
Ron Hunsinger wrote:
<snip>

> In other words, if you write:
>
> T f();
>
> the only interpretation permitted by the grammar is that f is a function
> taking no parameters and returning T. No ambiguity to be resolved. If
> what
> you wanted was an explicitly default-constructed object of type T, you
> have
> to write that as:
>
> T f = T();
>

Or rather
T f; // of course

<snap>

--
Martin Fabian http://www.s2.chalmers.se/~fabian/
--
"Cheer up. It may never happen" (Edina Monsoon)

/* Remove NOSPAM from reply-to address to mail me */

Hyman Rosen

unread,
Jun 8, 2000, 3:00:00 AM6/8/00
to
hns...@sirius.com (Ron Hunsinger) writes:
> In other words, when the ambiguity is between one type of declaration and
> another type of declaration, the ambiguity is resolved in favor of
> interpreting it as a declaration.

The Standard is talking about the construct inside the parnetheses.
It can either be the declaration of a parameter, or a function-style
cast. The former is a declaration and the latter is an expression,
so we favor the declaration over the expression. That forces the
whole declaration to be a function declaration instead of an object
declaration.

OK?

Joerg Barfurth

unread,
Jun 9, 2000, 3:00:00 AM6/9/00
to
Ron Hunsinger <hns...@sirius.com> wrote:

> What bugs me is that:
>
> T f( T() );
>
> can be interpreted as:
>
> T f( T );
>
> with some redundant parentheses

Of course it can't (AFAIK you can't put redundant parentheses around
nothing).
But 'T ()' is a type in it own right, and the compiler will adjust the
first declaration to
T f( T (*)() );

> , making f a function taking a T
> parameter.

> Say what? I'm suppose to see that without having it pointed out? When
> what's "obviously" intended is to construct in f an object of type T
> using as parameter the default value of type T?

Isn't it obvious that this tries to declare a function that takes one
parameter which is a function taking no parameters and return T and
finally returns T. <g>

--
Jörg Barfurth joerg.b...@attglobal.net
--------------- using std::disclaimer; ------------------
Software Engineer joerg.b...@germany.sun.com
Star Office GmbH http://www.sun.com/staroffice

Jim Hill

unread,
Jun 14, 2000, 3:00:00 AM6/14/00
to
Martin Fabian <fabian...@s2.chalmers.se> wrote:

> > T f = T();
> Or rather
> T f; // of course

Not if T is POD.

Jim

Biju Thomas

unread,
Jun 14, 2000, 3:00:00 AM6/14/00
to
Jim Hill wrote:
>
> Martin Fabian <fabian...@s2.chalmers.se> wrote:
>
> > > T f = T();
> > Or rather
> > T f; // of course
>
> Not if T is POD.
>

It is a problem only with builtin types, not with other PODs (such as
plain structs).

--
Biju Thomas

Reply all
Reply to author
Forward
0 new messages