Can I extern the entire namespace? - c++

Is there a method to declare a namespace with the extern modifier so that the namespace's entire content is externally linked?

You seem to be asking two questions. One regarding external linkage and one regarding the extern specifier.
Regarding the linkage, there is not really a need for such a syntax.
External linkage is already the default at namespace scope, whether in the global namespace or another namespace, except for const non-template non-inline variables and members of anonymous unions. (https://en.cppreference.com/w/cpp/language/storage_duration#internal_linkage)
So the other way around, syntax to make all names in a namespace have internal linkage, is more likely to be required and this is possible with unnamed namespaces
namespace {
//...
}
in which all declared names have internal linkage.
Regarding the extern specifier used to turn a variable definition into just a declaration at namespace scope or to give it external linkage explicitly, I am not aware of any syntax to apply it to a whole namespace. You will have to specify it explicitly on each variable.

Related

does linkage rules apply to namespace just like global names?

I've read Translation units and linkage, and it says:
The concept of linkage applies only to global names. The concept of linkage does not apply to names that are declared within a scope. A scope is specified by a set of enclosing braces such as in function or class definitions.
It says "The concept of linkage applies only to global names" but didn't mention namespace scope. However, I saw namespace scope in some case we have to use extern to make some variables available in other files:
// constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
namespace Constants
{
// since the actual variables are inside a namespace,
// the forward declarations need to be inside a namespace as well
extern const double pi;
extern const double avogadro;
extern const double my_gravity;
}
#endif
// constants.cpp
namespace Constants
{
// actual global variables
extern const double pi(3.14159);
extern const double avogadro(6.0221413e23);
extern const double my_gravity(9.2); // m/s^2 -- gravity is light on this planet
}
So what is the official definition? Is it true that linkage concept only apply to global, maybe namespace is part of global?
Namespaces are orthogonal to the distinction between global and local symbols. Namespaces just augment the name of a symbol, they don't change anything else. So, if you have a global variable, and put it inside a namespace it is still global variable, with external linkage.
The exception is when you put something inside an unnamed namespace. In this case, since there is no possible way code in one source file could reference a symbol in an unnamed namespace declared in another file, it is effectively a static symbol, and thus effectively has internal linkage.
Linkage applies to names basic.link/3:
A name is said to have linkage when it might denote the same object, reference, function, type, template, namespace or value as a name introduced by a declaration in another scope:
When a name has external linkage, the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.
When a name has module linkage, the entity it denotes can be referred to by names from other scopes of the same module unit ([module.unit]) or from scopes of other module units of that same module.
When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit.
When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.
Names of variables at namespace scope have external linkage unless they meet certain exceptions. basic.link/5.8 For example, non-extern const variables at namespace scope have internal linkage. basic.link/4.2
And yes, global scope is a namespace scope. basic.scope.namespace/4
Here is the relevant section of the spec pertaining to linkage.
And a relevant snippet:
Indicating by default namespaces have external linkage, minus the exceptions given.

Can reserved function names be overloaded?

This question is a follow-up question of this one.
Consider the following program:
#include <cmath>
// meaningless, only for language-lawyer purpose
void abs(void*) {}
int main(){
abs(nullptr);
}
Does this program result in undefined behavior?
The related part in the standard is [extern.names]/4:
Each function signature from the C standard library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
I'm not sure whether overloading is permitted.
There are two parts to this statement, as it talks about names (from the C standard) that are reserved (for C++ implementations). In particular,
Part 1: Each function signature from the C standard library declared
with external linkage
This includes the C library function abs
Part 2: is reserved to the implementation for use as a function
signature with both extern "C" and extern "C++" linkage, or as a name
of namespace scope in the global namespace.
So the name ::abs is reserved for the C++ implementation. You can't use it. Overloading is irrelevant.
tl;dr -
yes, you can
http://www.eel.is/c++draft/reserved.names#extern.names
Pulling in the rest of the context:
20.5.4.3.2: If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by this Clause, its behavior is undefined.
And then also
20.5.4.3.3.2 Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.
20.5.4.3.3.4 Each function signature from the C standard library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage,182 or as a name of namespace scope in the global namespace.
These suggest you can, as it is only the signature that is reserved.
Bonus for namespace ::std
http://www.eel.is/c++draft/library#namespace.std
20.5.4.2.1.1 Unless otherwise specified, the behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std.
http://en.cppreference.com/w/cpp/language/extending_std has summarised the exceptions

Linkage of a variable defined in a namepace and used in multiple translation units

In C, to use a variable in multiple translation units, we need to
make sure the variable has external linkage.
Similarly, in C++, if I want a variable defined in a namespace to be used in
multiple translation units, does the variable have to have external
linkage? How shall I use namespace and linkage together properly?
What is the default linkage of a variable defined in a namespace?
Thanks.
It works the same as C, except with 'namespace xyz { }' around it, so in your header, you'd have:
namespace xyz { extern int myglobal; }
and in the source file where you define it, its storage and initialize it, you would have
namespace xyz { int myglobal = 0; }
I'll say as an tangential style comment, that using globals in this way is really not very common in C++; there's usually better ways of creating a shared global state, like static class members (which allows you to create access restrictions by making it protected/private and limiting access through static member functions).

Why can't I define a variable at global scope after declaring it in an unnamed namespace?

In my understanding:
Names declared in an unnamed namespace are added to the enclosing namespace scope and visible in that translation unit.
With the extern specifier, a variable is not automatically defined (default-initialized).
I would expect the following to declare a variable and then define the same variable:
// Declare ::<unnamed>::my_obj with internal linkage and add my_obj to the
// enclosing namespace scope (the global namespace scope).
namespace { extern int my_obj; }
// Expected: Define the variable declared above.
// Actual: Declare and define a new object, ::my_obj.
int my_obj(42);
Instead, it declares two different objects, and warns me about the unused extern int my_obj.
Why doesn't the second my_obj define the first my_obj? Isn't it in scope?
The statement "names declared in an unnamed namespace are added to the enclosing namespace scope" does not mean that members of unnamed namespace become full-fledged members of enclosing namespace. This addition is performed by an implicit using-directive. Such addition makes these names visible to name lookup, but does not make them literal members of the enclosing namespace for other purposes.
The problem you have in your code is the same as the one in the following snippet
namespace A
{
void foo();
}
using namespace A;
void foo() // <- Defines `::foo`, not `A::foo`
{
}
// `A::foo` remains undefined
Despite the fact that we explicitly "added" names from A to the global namespace, it still does not mean that we can define A::foo as a member of global namespace using unqualified name foo.
In order to define A::foo in the above example you still have to refer to it using its qualified name A::foo. With unnamed namespaces this is impossible for obvious reasons.
P.S. Compilers typically implement unnamed namespaces as namespaces with internal compiler-generated names. If you somehow figured out a "hack" to discover that name, technically you'd probably be able to define your my_obj separately by using a qualified name in the definition. But keep in mind that the hidden namespace name is different in different translation units, thus producing a unique my_obj variable in each translation unit.
An unnamed namespace is not a global namespace. It is a specific namespace that is visible only within the translation unit in which it appears.
This cppreference page describes this in more detail.
If you are trying to use a symbol defined in an unnnamed namespace within the same translation unit -- just use it! It's in scope. You don't need an extern
from https://msdn.microsoft.com/en-us/library/2tx32sw2.aspx :
A variable declared with the extern storage-class specifier is a reference to a variable with the same name defined at the external level in any of the source files of the program. The internal extern declaration is used to make the external-level variable definition visible within the block. Unless otherwise declared at the external level, a variable declared with the extern keyword is visible only in the block in which it is declared.
Since the object is declared in a namespace, it must be defined in the same namespace (or rather, if a name is used as a declaration in one namespace and a definition outside that namespace, it refers to two different entities). That it is visible at file scope does not mean that it is a member of that namespace; I think the assertion that —
Names declared in an unnamed namespace are added to the enclosing
namespace scope
— does not mean what you think it does.
The C++11 standard says that An unnamed-namespace-definition behaves as if it were replaced by:
[inline] namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }
(paraphrasing slightly for formatting; the initial "inline" is optional, appearing iff it appears in the unnamed namespace definition).
So, would you expect in this:
namespace a_name {
extern int a;
}
using namespace a_name;
int a = 4;
... that the first mention of a (inside the namespace) would declare the variable and the second define it? (If you would, at least this is consistent. But if you wouldn't, you need to recognize that the standard specifically says that you should get the same behavior from the unnamed namespace).
I don't believe there is any mechanism to declare a member in one namespace and provide the definition for the same member within another namespace, even if the member is visible in the second namespace.
To address comments below:
Yes, extern causes the declaration not to be a definition. I have removed the statement saying that extern had no effect, which was mainly in reference to linkage; that extern does not grant a name within the unnamed namespace external linkage is true, since C++11 (including amendments). Although in C++03 it may have technically granted external linkage, this was only as an attribute of the declaration/definition; the symbol was still not visible outside the translation unit and had no special visibility to the linker. The significance of extern on a member of the unnamed namespace in C++03 then apparently boils down to usability of that member as a constant expression, if it is a const-qualified pointer.
The example that was linked in a comment, following another comment stating that the linkage determined visibility of symbols to the linker which can have consequences, was perhaps intended to demonstrate that (in C++11) symbols in the unnamed namespace can have external linkage, and that non-external linkage pointers cannot be used as as template arguments (i.e. contexts requiring a constant expression) even when declared const. It did indeed fail to compile with GCC, however it compiles successfully with Clang and with the Intel compiler Icc. With any of the three compilers, the symbols declared in the inline namespace are local symbols at the link level (as can be seen using objdump for example) - there is no causal relationship between symbol visibility at the linker level and the error produced.C++11 explicitly makes a statement (3.5) to the effect that
extern-qualified symbols shall have internal linkage if they
reside in the unnamed namespace (specifically: A name having
namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of - a variable; or ...). Furthermore, const-declared variables with internal linkage should be usable in contexts requiring a constant expression. By reading the standard, there can be little argument that the GCC compiler is behaving incorrectly in this case.

global scope vs file scope

What is right to say about global variable:
If it is declared without static keyword:
It has file scope and external linkage OR
It has program scope and is visible to all files in the program
If it is declared with static keyword:
It has global scope and internal linkage OR
It has file scope and internal linkage
And how is global namespace scope related to this?
This notions are really confusing altough i think I understand how it works, but at different places they call it in different ways so i don't know which is right.
The answers for the first question are both incorrect.
The variable will have extrenal linkage indeed but will be visible in other program units only if it is declared in it.
As for the second question then indeed the variable will have file scope and internal linkage.
Any variable declared outside some explicitly specified namespace is considered as declared in the global namespace. Variavles with external or internal linkage can be declared in any namespace including the global namespace.
We are speaking about variables that are declared outside any function.