C++ Logo

std-discussion

Advanced search

Re: forward declaration inside another function in a namespace

From: Federico Kircheis <federico_at_[hidden]>
Date: Sun, 30 Jun 2024 11:45:33 +0200
On 30/06/2024 01.53, Andrew Schepler wrote:
> On Sat, Jun 29, 2024 at 8:35 AM Federico Kircheis via Std-Discussion
> <std-discussion_at_[hidden]
> <mailto:std-discussion_at_[hidden]>> wrote:
>
> Hello to everyone,
>
> I am failing to understand if following code is really invalid.
> I've looked at the standard, but I am missing where the relevant
> information is.
>
>
> The entities found when searching for a name in a namespace scope are
> not always the same as the entities which are members of that namespace
> (and have names). The differences come up with using-declarations,
> using-directives, friend declarations, extern variables in block scope,
> and this situation: function declarations in block scope.
>
> The relevant rule in C++20 and earlier was [basic.link]/7:
>
> (6) The name of a function declared in block scope and the name of a
> variable declared by a block scope extern declaration have linkage. ...
>
> (7) When a block scope declaration of an entity with linkage is not
> found to refer to some other declaration, then that entity is a
> member of the innermost enclosing namespace. However such a
> declaration does not introduce the member name in its namespace scope.
>
>
> C++23 revised the all scope and name lookup language to be more precise.
> The same rule is now found in [dcl.meaning.general]/(3.5):
>
> If the declaration inhabits a block scope /S/ and declares a
> function ([dcl.fct]) or uses the extern specifier, the declaration
> shall not be attached to a named module ([module.unit]); its target
> scope is the innermost enclosing namespace scope, but the name is
> bound in /S/.
>
> [Example 3:
>
> namespace X {
>
> void p() {
>
> q(); // error: q not yet declared
>
> extern void q(); // q is a member of namespace X
>
> extern void r(); // r is a member of namespace X
>
> }
>
> void middle() {
>
> q(); // error: q not found
>
> }
>
> void q() { /* ... */ } // definition of X::q
>
> }
>
> -- end example]
>
> Here "target scope" determines whether a declaration is a member of a
> namespace or a class or neither ([basic.scope.scope]/2). A name "bound"
> in a scope influences the name lookup rules: [basic.lookup.general]/3
> defines "single search" in terms of "bound" names,
> [class.member.lookup]/1 defines a "search in a scope" in terms of
> "single search". In particular for your examples, the qualified-id
> ::a::bar requires that the name "bar" was bound in namespace "a" or in
> an inline namespace of "a", or can be found via a using-directive
> ([namespace.qual]), but it was not.
>
> -- Andrew Schepler
>


Thank you Andrew for your time and the quotes, I'll give a closer look
to those sections.

This triggers a follow-up question

> The entities found when searching for a name in a namespace scope are
> not always the same as the entities which are members of that namespace
> (and have names). The differences come up with using-declarations,
> using-directives, friend declarations, extern variables in block scope,
> and this situation: function declarations in block scope.

Is this difference desirable or necessary?
Function declarations in block scope do not happen often, but since
"using-declarations, using-directives, friend declarations, extern
variables in block scope" are also affected, it seems desirable to me to
have the same rules in all situations.

Received on 2024-06-30 09:45:44