namespace X {
void f();
}
void X::f() {
void g();
g();
}
Have I declared ::g
, or X::g
?
clang 3.5 will compile and link this if I add a definition of X::g
:
namespace X {
void f();
}
void X::f() {
void g();
g();
}
void X::g() { }
gcc 4.9.1 rejects the definition with the message:
error: ‘void X::g()’ should have been declared inside ‘X’
but if I define g
in the global namespace instead, gcc seems to change it's mind and complain about the opposite:
Undefined symbols for architecture x86_64: "X::g()", referenced from: X::f() in ccABCDEF.o
Because it is also illegal to declare void ::g()
inside of f
, it seems that it isn't possible to have a function-scope forward declaration of global function in a namespace function. Am I missing something? What exactly are the scoping rules here?
g++ (GCC) 4.9.1; Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
The scope of a variable is the range of functions that have direct access to the variable to set, modify, or acquire its value. When you define a local (i.e., nonglobal) variable within a function, its scope is normally restricted to that function alone.
A nested function is a function defined inside another function. Nested functions are supported as an extension in GNU C, but are not supported by GNU C++. The nested function's name is local to the block where it is defined.
C does not enable nested functions because we cannot define a function within another function in C. It is possible to declare a function within a function, but this is not a nested function.
A nested function is a function defined inside the definition of another function. It can be defined wherever a variable declaration is permitted, which allows nested functions within nested functions. Within the containing function, the nested function can be declared prior to being defined by using the auto keyword.
Function declarations at block scope have linkage. [basic.link]/6:
The name of a function declared in block scope and [..] have linkage.
But such block scope declarations with linkage do not introduce any names into enclosing namespaces. [basic.link]/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.
You have therefore neither declared ::g
nor X::g
. Defining it via
void X::g() {}
is ill-formed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With