Topic: forward declaration inside function definition


Author: Gabriel Dos_Reis <gdosreis@korrigan.inria.fr>
Date: 2000/11/24
Raw View
James Kanze <James.Kanze@dresdner-bank.de> writes:

| Gabriel Dos_Reis wrote:
|
| > Francis Glassborow <francis.glassborow@ntlworld.com> writes:
|
| > | In article <8vbr7n$e3i$1@bambi.zdv.Uni-Mainz.DE>, Richard B. Kreckel
| > | <Richard.Kreckel@Uni-Mainz.DE> writes
| > | >Does anybody know if forward declarations inside function definitions
| > | >are legal in C++ and maybe point to the corresponding section in the
| > | >standard?  Here is an example of what I mean:
|
| > | >#include <iostream>
|
| > | >// do we need a forward declartion here?
| > | >struct myint;
|
| > | >// or is it enough to declare it here?
| > | >int foo(struct myint*);
|
| > | Unless this is a place where C++ is different from C (which I do
| > | not think it is) the use of myint in that context is scoped to
| > | function declaration, and unless it binds to an already declared
| > | myint, it has no significance outside the declaration. So the
| > | answer is that it is syntactically correct but is not a forward
| > | declaration visible in an enclosing scope.
|
| > I don't think so. The Standard says in 3.3.1/5:
|
| >   The point of declaration of a class first declared in an
| >   elaborated-type-specifier is as follows :
|
| >   [ ... ]
|
| >   -- for an elaborated-type-sepcifier of the form
|
| >         class-key identifier
|
| >      if the elaborated-type-sepcifier is used in the
| >      decl-specifier-seq or parameter-declaration-clause of a
| >      function defined in namespace scope, the identifier is declared
| >      as a class-name in the namespace that contains the declaration;
| >      [...]
|
| And it says in 3.4 that "The name lookup rules apply uniformly to all
| names...", and there is a function prototype scope (3.3.3).  Still, in
| conjunction with the text in 3.3.3 (which explicitly mentions
| parameters), I suspect that the exception to the rule in 3.4 is
| intentional (and a subtle incompatibility with C).

As I explained in another message, you are confusing name lookup rules
with point of declaration rules.  They are independent concepts.

Point of declaration rules don't apply uniformly to all names: they
depend on the entity being named.

Name lookup rules are applied to find *declarations* associated with a
name when checking the validity of its use.

| Would someone who was involved with the formulating of these
| paragraphs care to comment.  In particular, I'd like to know what the
| actual intent was, and if it is as seems, what the motivation was for
| deviating from C in this context.

I'm also interested in having explanation( but for a different
reason).  The rules in 3.3.3 and 3.4 are not in conflict; for
class-names declared in a function declarator, the relevant rule is
3.3.1/5; not 3.3.3 since tha rule explicitly says it is about names of
function parameters.

--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: wmm@fastdial.net
Date: 2000/11/27
Raw View
In article <3A1CE361.67CA338A@dresdner-bank.de>,
  James Kanze <James.Kanze@dresdner-bank.de> wrote:
> Gabriel Dos_Reis wrote:
>
> >   The point of declaration of a class first declared in an
> >   elaborated-type-specifier is as follows :
>
> >   [ ... ]
>
> >   -- for an elaborated-type-sepcifier of the form
>
> >         class-key identifier
>
> >      if the elaborated-type-sepcifier is used in the
> >      decl-specifier-seq or parameter-declaration-clause of a
> >      function defined in namespace scope, the identifier is declared
> >      as a class-name in the namespace that contains the declaration;
> >      [...]

> Would someone who was involved with the formulating of these
> paragraphs care to comment.  In particular, I'd like to know what the
> actual intent was, and if it is as seems, what the motivation was for
> deviating from C in this context.

There are two interacting factors that motivate this decision.
First, elaborated-type-specifiers are sometimes references to
previously-declared types and sometimes declarations of new
types.  In general, whenever the lookup for the name in an
elaborated-type-specifier does not find a previous declaration,
the name is declared as a new type, and that applies to
parameter declarations as well.

Second, C++ relies on name equivalence, not type equivalence,
for linkage purposes.  That is, two function declarations can
only declare the same function if (inter alia) the names of
types used in the corresponding parameter declarations refer
to the same types.

If an elaborated-type-specifier used in a parameter declaration
is determined to declare a new type, and that type name were to
have function prototype scope, the function could never be
defined -- the corresponding parameter in the definition would
necessarily have a different type from the one in the declaration.
That didn't seem like a particularly useful outcome.

There are really only three choices for such a case:

1) Make such a function declaration ill-formed.

2) Put the new type name into function prototype scope and allow
the (useless) declaration, which will only be discovered when
the programmer attempts to use the declaration to call the
nonexistent function (with attendant head-scratching -- "But
the definition's right here!" :-).

3) Define the point of declaration for these elaborated-type-
specifiers to be someplace that will allow the function to be
defined and used.

Pragmatically, #3 seemed the most attractive and was adopted.

(This is really pretty similar to the way friend declarations
are handled; see the note in 3.3p4.  In fact, in earlier
drafts of the Standard, the connection was more explicit, but
friend declarations have diverged somewhat as a result of
the evolution of templates and the corresponding use of Koenig
lookup.)

--
William M. Miller, wmm@fastdial.net
Vignette Corporation (www.vignette.com)


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: James Kanze <James.Kanze@dresdner-bank.de>
Date: 2000/11/23
Raw View
Gabriel Dos_Reis wrote:

> Francis Glassborow <francis.glassborow@ntlworld.com> writes:

> | In article <8vbr7n$e3i$1@bambi.zdv.Uni-Mainz.DE>, Richard B. Kreckel
> | <Richard.Kreckel@Uni-Mainz.DE> writes
> | >Does anybody know if forward declarations inside function definitions
> | >are legal in C++ and maybe point to the corresponding section in the
> | >standard?  Here is an example of what I mean:

> | >#include <iostream>

> | >// do we need a forward declartion here?
> | >struct myint;

> | >// or is it enough to declare it here?
> | >int foo(struct myint*);

> | Unless this is a place where C++ is different from C (which I do
> | not think it is) the use of myint in that context is scoped to
> | function declaration, and unless it binds to an already declared
> | myint, it has no significance outside the declaration. So the
> | answer is that it is syntactically correct but is not a forward
> | declaration visible in an enclosing scope.

> I don't think so. The Standard says in 3.3.1/5:

>   The point of declaration of a class first declared in an
>   elaborated-type-specifier is as follows :

>   [ ... ]

>   -- for an elaborated-type-sepcifier of the form

>         class-key identifier

>      if the elaborated-type-sepcifier is used in the
>      decl-specifier-seq or parameter-declaration-clause of a
>      function defined in namespace scope, the identifier is declared
>      as a class-name in the namespace that contains the declaration;
>      [...]

And it says in 3.4 that "The name lookup rules apply uniformly to all
names...", and there is a function prototype scope (3.3.3).  Still, in
conjunction with the text in 3.3.3 (which explicitly mentions
parameters), I suspect that the exception to the rule in 3.4 is
intentional (and a subtle incompatibility with C).

Would someone who was involved with the formulating of these
paragraphs care to comment.  In particular, I'd like to know what the
actual intent was, and if it is as seems, what the motivation was for
deviating from C in this context.

Also, this thread seems to be rapidly moving to a point where
comp.std.c++ would be more appropriate.  I've cross-posted, and set
the followup's appropriately.

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


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

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]