Local function declaration inside namespace - c++

In such a situation
namespace n {
void f() {
void another_function();
}
}
Should the function another_function be defined inside the namespace n or outside? VS 2012 (with the November CTP) says it should be outside, and GCC 4.7.2 on the Mac says it should be inside. If I do the wrong one, I get undefined symbol errors from the linkers.
I generally trust GCC to be more compliant to the standard, but this is C++ and you can never be sure.

C++11 3.5 (as well as C++03)
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.
The declaration in your example declares n::another_function.

According to N3485 7.3.1 [namespace.def]/6, the correct answer is n::another_function.
The enclosing namespaces of a declaration are those namespaces in
which the declaration lexically appears, except for a redeclaration of
a namespace member outside its original namespace (e.g., a definition
as specified in 7.3.1.2). Such a redeclaration has the same enclosing
namespaces as the original declaration. [ Example:
namespace Q {
namespace V {
void f(); // enclosing namespaces are the global namespace, Q, and Q::V
class C { void m(); };
}
void V::f() { // enclosing namespaces are the global namespace, Q, and Q::V
extern void h(); // ... so this declares Q::V::h
}
void V::C::m() { // enclosing namespaces are the global namespace, Q, and Q::V
}
}
—end example ]

Related

Why does the using directive not "associate" with ordinary functions?

According to this question it is valid to define class methods after a using directive, instead of enclosing them within a namespace block.
However, that seems not to be the case for ordinary functions. Consider:
Greeting.hh
#pragma once
namespace NS
{
class Greeting
{
public:
void hello();
};
void otherHello();
}
Greeting.cc
#include "Greeting.hh"
#include <iostream>
using namespace NS;
void Greeting::hello()
{
std::cout << "Greeting::hello" << std::endl;
}
void otherHello()
{
std::cout << "otherHello" << std::endl;
}
main.cc
#include "Greeting.hh"
int main()
{
NS::Greeting o;
o.hello();
NS::otherHello();
}
This won't compile, yielding the following error message:
undefined reference to `NS::otherHello()'
Further inspection indicates that otherHello's symbol is not preceded by the namespace, while Greeting::hello's is:
g++ -std=c++14 -pedantic -Wall -c Greeting.cc
nm -C Greeting.o | grep T
000000000000002a T otherHello()
0000000000000000 T NS::Greeting::hello()
Does this contradict with the Standard reference from the accepted answer?
"During unqualified name lookup (3.4.1), the names appear as if they
were declared in the nearest enclosing namespace which contains both
the using-directive and the nominated namespace."
What's important to remember is that
Function declarations in different namespaces don't interfere with each other.
A definition of a function is also a declaration.
[namespace.def/4]
The enclosing namespaces of a declaration are those namespaces in
which the declaration lexically appears, except for a redeclaration of
a namespace member outside its original namespace (e.g., a definition
as specified in [namespace.memdef]). Such a redeclaration has the same
enclosing namespaces as the original declaration.
So let's look at the otherHello definition. Where does it lexically appear? In the global namespace of course. That's also the point of declaration for it. Which means the enclosing namespace is the global one, and you end up with a declaration of ::otherHello.
So no, this doesn't contradict the standard quote from the accepted answer to the other question. Member functions can be defined outside of the class, so long as they are qualified by their class name ([class.mfct/4]):
If the definition of a member function is lexically outside its class
definition, the member function name shall be qualified by its class
name using the ​::​ operator.
So we need only ask, does Greeting name the same class as NS::Greeting? Why, yes it does. The using directive is responsible for that.
I'll add this segment in the hope of clarifying. Consider this code snippet:
namespace NS1 {
namespace NS2 {
void hello();
}
}
using namespace NS1;
void NS2::hello() {
}
int main() {
NS1::NS2::hello();
return 0;
}
When the compiler encounters NS2::hello being defined it preforms name lookup for that declarator id. According to [basic.lookup.qual/3]:
In a declaration in which the declarator-id is a qualified-id, names
used before the qualified-id being declared are looked up in the
defining namespace scope; names following the qualified-id are looked
up in the scope of the member's class or namespace.
So NS2 is looked up in the defining scope (the global one), and according to the unqualified name lookup rule you quoted, it is found and resolved as NS1::NS2. That's how NS2::hello is associated with NS1::NS2::hello and resolved as defining it.
In the global namespace of the OP, otherHello isn't preceded by anything. Therefore name lookup doesn't occur. It immediately defines that function in the enclosing namespace, as I previously quoted.

Local extern variable declaration with using-directive in the nearest enclosing scope

Is this program well-formed according to the c++ standard?
namespace X { int i = 1; }
using namespace X;
int main() {
extern int i;
i = 2;
}
I get different results with different compilers:
GCC and Clang gives a linker error: Undefined reference to i.
Visual c++ accepts the program.
[basic.link]/p6:
If there is a visible declaration of an entity with linkage having the same name and type, ignoring entities declared outside the innermost enclosing namespace scope, the block scope declaration declares that same entity and receives the linkage of the previous declaration. If there is more than one such matching entity, the program is ill-formed. Otherwise, if no matching entity is found, the block scope entity receives external linkage.
X::i was declared outside the innermost enclosing namespace of the extern declaration (i.e the global namespace) so it is ignored. This means no declaration was found for i and therefore extern int i is a declaration of a new variable named i with external linkage.
Your program will compile, but will not link if the block-scope i is odr-used.

Unnamed and Named Namespace Resolution

Should a reference to a name that exists in both an unnamed namespace and the local named namespace result in a error for ambiguity or is the resolution well-defined? I'm seeing the following work fine on G++ and Clang, less well on MSVC.
namespace Foo
{
class Bar
{
public:
int x;
};
}
namespace
{
class Bar
{
public:
int y;
};
}
namespace Foo
{
void tester()
{
Bar b;
}
}
int main()
{
Foo::tester();
return 0;
}
GCC and Clang are right. Within Foo::tester, an unqualified use of Bar unambiguously refers to Foo::Bar.
Unqualified lookup is specified by C++11 3.4.1/1:
the scopes are searched for a declaration in the order listed in each of the
respective categories; name lookup ends as soon as a declaration is found for the name.
The scopes searched for the use of a name in a function are listed in 3.4.1/6:
A name used in the definition of a function [...] that is a member of namespace N [...] shall be declared before its use in the block [...] or, shall be declared before its use in namespace N or, if N is a nested namespace, shall be declared before its use in one of N’s enclosing namespaces.
In this case, the function is a member of Foo, so Foo is searched before the enclosing (global) namespace, which includes the unnamed namespace. Foo::Bar is found there, and lookup ends.

Function definition as qualified id

Why the following code is compiled successfully:
#include <stdio.h>
namespace B
{
void foo();
int i=3;
}
void B::foo()
{
i=65;
}
int main(){ }
and the following is not compiled succefully:
#include <stdio.h>
namespace B
{
void foo()
{
i=65;//error: ‘i’ was not declared in this scope
}
int i=3;
}
int main(){ }
I would like to find a reference from the standard clarified this moment.
Since you want quotes 3.4.1 [basic.unqual.lookup]:
/4 A name used in global scope, outside of any function, class or user-declared namespace, shall be declared before its use in global scope.
/6 A name used in the definition of a function following the function’s declarator-id28 that is a member of namespace N (where, only for the purpose of exposition, N could represent the global scope) shall be declared before its use in the block in which it is used or in one of its enclosing blocks (6.3) or, shall be declared before its use in namespace N or, if N is a nested namespace, shall be declared before its use in one of N’s enclosing namespaces.
In the first example, foo is declared in namespace B, so will search for an i inside its namespace first (and finds such an i, because the implementation of foo is AFTER the namespace declaration of i). In the second example you are declaring i after the definition of foo, so f does not "see" i.

Unnamed namespace access rules

I was looking over section 7.3.1.1 in the C++03 standard expecting to find some description of the access rules for items defined in an unnamed namespace.
The rules seem to be a little different for unnamed namespaces, since you cannot fully qualify access to items in one. I know that at least within the same translation unit, one can access items in an unnamed namespace as if they were not in a namespace. For example:
namespace {
int foo;
}
void something()
{
foo = 4;
}
If the namespace had a name, you could not do this. So, where are the rules defined in the standard for these exceptional rules that apply to unnamed namespaces?
An anonymous namespace is basically treated as:
namespace unique_per_TU
{
// Stuff
}
using namespace unique_per_TU;
I'll try to find the reference here in a minute.
EDIT:
It appears you already found it in 7.3.1.1/1
An unnamed namespace definition behaves as if it were replaced by
namespace unique { /* empty body */ }
using namespace unique;
namespace unique { namespacebody }
where all occurrences of unique in
a translation unit are replaced by the same identifier and this
identifier differs from all other identifiers in the entire program.
The "fake" using already brings the namespace members into the global namespace as you discovered.
Apart from the standard quote which defines Unnamed Namespaces in 7.3.1.1/1,
This is explicitly stated in one of the examples in
3.3.5/1 Namespace Scope:
The declarative region of a namespace-definition is its namespace-body. The potential scope denoted by an original-namespace-name is the concatenation of the declarative regions established by each of the namespace-definitions in the same declarative region with that original-namespace-name. Entities declared in a namespace-body are said to be members of the namespace, and names introduced by these declarations into the declarative region of the namespace are said to be member names of the namespace. A namespace member name has namespace scope. Its potential scope includes its namespace from the name’s point of declaration (3.3.1) onwards; and for each using-directive (7.3.4) that nominates the member’s namespace,
the member’s potential scope includes that portion of the potential scope of the using-directive that follows the member’s point of declaration.
>[Example:
namespace N {
int i;
int g(int a) { return a; }
int j();
void q();
}
namespace { int l=1; }
// the potential scope of l is from its point of declaration
// to the end of the translation unit
namespace N {
int g(char a) // overloadsN::g(int)
{
return l+a; // l is from unnamed namespace
}
int i; // error: duplicate definition
int j(); // OK: duplicate function declaration
int j() // OK: definition ofN::j()
{
return g(i); // callsN::g(int)
}
int q(); // error: different return type
}
—end example]
Note the wordings:
the potential scope of l is from its point of declaration to the end of the translation unit