extern in namespace scope - gcc vs clang vs msvc - c++

I've tested the seemingly strange code example below with the newest gcc, clang, and MSVC; both clang and gcc give link errors, but MSVC compiles and links without any problem. Which one is correct?
// foo.h
#pragma once
namespace A
{
class foo
{
public:
foo();
void print();
};
}
// foo.cpp
#include <iostream>
#include "foo.h"
int* p = nullptr;
using namespace A;
foo::foo()
{
p = new int(5);
}
void foo::print()
{
extern int* p;
std::cout << *p;
}
#include "foo.h"
int main()
{
A::foo f;
f.print();
}
gcc and clang:
foo.cpp:(.text+0x35): undefined reference to 'A::p'

Both GCC and Clang are standard compliant. The example and explanation are given in the standard [basic.namespace]/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.
[ 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

C++ extern variable why can't I define it in main

use.cpp
#include "my.h"
int main()
{
int foo = 7;
print_foo();
print(99);
}
my.h
#pragma once
extern int foo;
void print_foo();
void print(int i);
my.cpp
#include<iostream>
#include "my.h"
void print_foo()
{
std::cout << foo;
}
void print(int i)
{
std::cout << i;
}
So my question is pretty simple I declare an extern int foo in the header file then I DEFINE foo in main, why does this not work? If I don't define foo in main and define it outside of main in use.cpp then it works but when I define it in main() it doesn't. Why?
At global scope, the declaration
extern int foo;
declares a variable named foo that has external linkage, meaning that it might be defined in another translation unit.
At block scope (i.e., as a statement in the body of a function), the definition
int foo = 7;
has no linkage. That means that the compiler will never consider this foo to be the same entity as another foo from another scope. Therefore, this simply creates another variable that's unrelated to the global one, and does not initialize the global one.

Is a fully qualified class name down to global scope ever required for out-of-line member function definitions?

This question got me wondering whether it is ever useful/necessary to fully qualify class names (including the global scope operator) in an out-of-class member function definition.
On the one hand, I've never seen this done before (and the syntax to properly do so seems obscure). On the other, C++ name lookup is very non-trivial, so maybe a corner case exists.
Question:
Is there ever a case where introducing an out-of-class member function definition by
ReturnType (::Fully::Qualified::Class::Name::MemberFunctionName)(...) { ... }
would differ from
ReturnType Fully::Qualified::Class::Name::MemberFunctionName(...) { ... } (no global scope :: prefix)?
Note that member function definitions must be put into a namespace enclosing the class, so this is not a valid example.
A using-directive can cause Fully to be ambiguous without qualification.
namespace Foo {
struct X {
};
}
using namespace Foo;
struct X {
void c();
};
void X::c() { } // ambiguous
void ::X::c() { } // OK
It's necessary if one is a masochist and enjoys writing stuff like this
namespace foo {
namespace foo {
struct bar {
void baz();
};
}
struct bar {
void baz();
};
void foo::bar::baz() {
}
void (::foo::bar::baz)() {
}
}
One can of course write the second overload as foo::foo::bar::baz in global scope, but the question was whether or not the two declarations can have a different meaning. I wouldn't recommend writing such code.
If a using directive is used then there can be a confusing code.
Consider the following demonstrative program
#include <iostream>
#include <string>
namespace N1
{
struct A
{
void f() const;
};
}
using namespace N1;
void A::f() const { std::cout << "N1::f()\n"; }
struct A
{
void f() const;
};
void ::A::f() const { std::cout << "::f()\n"; }
int main()
{
N1::A().f();
::A().f();
return 0;
}
So for readability this qualified name
void ::A::f() const { std::cout << "::f()\n"; }
shows precisely where the function is declared.

What is the meaning of the sentence referring to functions introduced by a using declaration?

I'm studying the C++03 Standard and am now reading [7.3.3]/11, but I'm having trouble understanding the following passage:
If a function declaration in namespace scope or block scope has the same name and the same parameter
types as a function introduced by a using-declaration, and the declarations do not declare the same function,
the program is ill-formed.
I haven't found any examples of this situation anywhere and I don't understand the meaning of this passage.
What it means is that:
namespace namespace_1
{
void foo(int number);
}
using namespace_1::foo;
void foo(int roll_no);
This means the program is ill-formed.
I believe it means to say that the function would be confusing to read. As at one point, the function definition would be using the passed int as an integer(general) but in the other case, we'd be using it as a roll_no.
This would also cause ambiguity in overloaded function matching.
The source you are citing gives an example just below the lines you have cited:
namespace B {
void f(int);
void f(double);
}
namespace C {
void f(int);
void f(double);
void f(char);
}
void h() {
using B::f; // B::f(int) and B::f(double)
using C::f; // C::f(int), C::f(double), and C::f(char)
f('h'); // calls C::f(char)
f(1); // error: ambiguous: B::f(int) or C::f(int)?
void f(int); // error: f(int) conflicts with C::f(int) and B::f(int)
}
The following program contains the error
#include <iostream>
namespace _1{
int f(){
std::cout << "_1::f\n";
}
}
namespace _2{
/*
*If a function declaration in namespace scope or block scope has the
*same name and the same parameter types as a function introduced by
* a using-declaration
*/
using _1::f;
// This is not the same function as introduced by the using directive
int f(){
std::cout << "_2::f\n";
}
}
int main(){
_2::f();
}
The diagnostic is
main.cpp: In function ‘int _2::f()’:
main.cpp:13:11: error: ‘int _2::f()’ conflicts with a previous declaration
int f(){
As a contrast, the following program is correct. The _1 namespace is introduced via a using directive.
#include <iostream>
namespace _1{
int f(){
std::cout << "_1::f\n";
}
}
namespace _2{
using namespace _1;
int f(){
std::cout << "_2::f\n";
}
}
int main(){
_2::f();
}
With the expected output
_2::f
As for the same situation in block scope you have
#include <iostream>
namespace _1{
int f(){
std::cout << "_1::f\n";
}
}
namespace _2{
int g(){
// As before but in block scope.
using _1::f;
int f();
f();
}
int f(){
std::cout << "_2::f\n";
}
}
int main(){
_2::f();
}
The diagnostic is identical
main.cpp: In function ‘int _2::g()’:
main.cpp:15:15: error: ‘int _2::f()’ conflicts with a previous declaration
int f();
^
The parallel construct of the successful sample above would be
#include <iostream>
namespace _1{
int f(){
std::cout << "_1::f\n";
}
}
namespace _2{
int g(){
using namespace _1;
int f();
f();
}
int f(){
std::cout << "_2::f\n";
}
}
int main(){
_2::g();
}
With the output
_2::f

static inlined function with static variables

After reading static variables in an inlined function, I wrote this test program:
main.cpp:
#include <iostream>
#include "a.h"
#include "f.h"
void g();
int main()
{
std::cout << "int main()\n";
f().info();
g();
}
a.h:
struct A
{
A() { std::cout << "A::A()\n"; }
void info() { std::cout << this << '\n'; }
};
f.h: (singleton local to each compilation unit because of the unnamed namespace)
namespace {
inline A& f()
{
static A x;
return x;
}
}
g.cpp:
#include <iostream>
#include "a.h"
#include "f.h"
void g()
{
std::cout << "void g()\n";
f().info();
}
The problem is that I don't get the same results with different compilers:
g++ 4.8.2: OK
int main()
A::A()
0x6014e8
void g()
A::A()
0x6014d0
clang++ 3.7.0: OK
int main()
A::A()
0x6015d1
void g()
A::A()
0x6015c1
icpc 15.0.2: no call to A::A() inside g() !
int main()
A::A()
0x601624
void g()
0x601620
Is this a bug in icpc ? Is the behaviour of the program not defined ? If I replace "namespace {...}" with "static" in f.h, A::A() is called inside g() as expected. Shouldn't the behaviour be the same?
If I remove "namespace {...}" in f.h, A::info() prints the same object address in main() and g(), and A::A() is called only once (with all compilers) as expected.
Since C++11 mandates names in unnamed namespaces to have internal linkage, every translation unit should have it's own version of f() and, as a result, it's own version of static A x. So gcc and clang are correct.
Seems like icpc is not following C++11 standard and instead following C++03, which allowed those names to be declared with external linkage. Since when you explicitly make f() internal by using static icpc follows the suit, I have a strong suspicion this is simply a bug.

implementing or defining class or function declared inside an unnamed/anonymous namespace

Is it legal to define the implementation of a function or class members outside the unnamed (anonymous) namespace they've been defined inside.
My compiler accepts it but I want to be sure it's legal
e.g.
////////////////
// foo.cpp
namespace {
struct X
{
void foo(int x);
};
}
// Is this legal?
void X::foo(int x)
{
}
The reason is I would like to avoid the unnecessary indentation imposed by our uncrustify formatting
It is really no different than the following, which is totally legit:
namespace ns {
struct s {
void f();
};
}
using namespace ns;
void s::f() { }
The names from the named namespace are brought into the global namespace and thus definitions can be provided for them there. The only difference with the unnamed namespace is that it has no name (really, it has some unique, unutterable name) and the using namespace is implicit.
#include <iostream>
using namespace std;
namespace
{
struct X
{
X(int);
int x_;
};
}
X::X(int x) : x_(x) {}
int main()
{
X x(5);
cout << x.x_ << "\n";
return 0;
}
Compiles (and runs) under gcc 4.6.0
Yes. It's perfectly legal. The difference an unnamed namespace makes is that, the content of the namespace is available only within the file it's declared. If it's in .h file then, it will be added to all the subsequent .cpp file and every .cpp file will have a unique copy of the contents of the namespace.
In fact it's a better way to declare a global static variable. Now see, what kind of difference it will make:
namespace {
struct X
{
void foo(int x);
};
int i; // declare this global variable
}
If you put this code inside a header file then, wherever that header file is #includeed, all those .cpp file will have a different copy of int i; inside them. Changing the value of i in one .cpp file doesn't affect the other .cpp file.
Moreover, it will not give linker error for multiple definitions, since it's in unnamed namespace.
Edit: To evaluate it more, define the namespace as following:
// x.h
namespace
{
struct X
{
void foo(int x)
{
static int c; // static inside the function
cout<<"a = "<<(c++)<<endl;
}
};
}
Now #include this header file in 2 different .cpp files. In both of them try to call foo() with object of X. It will print:
a = 0
a = 0
Which means that X::foo() in both the .cpp files are different. If you give the namespace a name and repeat the same thing, it will output
a = 0
a = 1
Thus unnamed namespace creates a different copy for each translation unit.
It's legal in your scenario, but in one scenario, it will cause compiler ambiguous error.
In case have another class in X.h:
// X.h
struct X
{
void foo(int x) { }
};
And in foo.cpp, need to use the X defined in X.h
////////////////
// foo.cpp
#include "X.h"
namespace {
struct X
{
void foo(int x);
};
// use the X declared in anonymous namespace
void test()
{
X x;
x.foo(3);
}
}
// reference to 'X' is ambiguous
void X::foo(int x)
{
}
void otherFunction()
{
// Use struct X in X.h
::X x;
x.foo(3);
}
if leave the implementation code out of the anonymous namespace, compiler complains ambiguous. If move the implementation code inside anonymous namespace, it works fine.