In C++, What Is a "Namespace Alias"

In C++, what is a namespace alias ?

A namespace alias is a convenient way of referring to a long namespace name by a different, shorter name.

As an example, say you wanted to use the numeric vectors from Boost's uBLAS without a using namespace directive. Stating the full namespace every time is cumbersome:

boost::numeric::ublas::vector<double> v;

Instead, you can define an alias for boost::numeric::ublas -- say we want to abbreviate this to just ublas:

namespace ublas = boost::numeric::ublas;


ublas::vector<double> v;

Namespace alias inside a namespace

The name x is introduced in the namespace a::b::c

namespace a::b::c
{
class xyz{

};

using x=xyz
}

So in the global namespace to refer to the name x you have to write

a::b::c::x

You could introduce the alias in the global namespace like

using x = a::b::c::xyz;

Alternatively you could use a using declaration like

using a::b::c::x;

in this case you can use the unqualified name x in the scope where the using declaration is placed.

What is the scope of a namespace alias in C++?

It's a block duration of validity. E.g If you define a namespace alias as below, the namespace alias abc would be invalid outside {...} block.



{
namespace abc = xyz;
abc::test t; //valid
}
abc::test t; //invalid

How to Alias a namespace and extend the original namespace based on the alias

Nope. It's unfortunately not possible. The rule, from [namespace.def], explicitly excludes aliases:

In a named-namespace-definition, the identifier is the name of the namespace. If the identifier, when looked up (3.4.1), refers to a namespace-name (but not a namespace-alias) that was introduced in the
namespace in which the named-namespace-definition appears or that was introduced in a member of the inline namespace set of that namespace, the namespace-definition extends the previously-declared namespace.
Otherwise, the identifier is introduced as a namespace-name into the declarative region in which the named-namespace-definition appears.

You cannot extend a namespace by alias, you can only extend a namespace by the original namespace name.

C# Namespace Alias qualifier (::) vs Dereferencing Operator (.)

This is a corner case :: (like the @ prefix) is there to deal with the fairly rare occurrences where a name conflicts between namespaces, classes and keywords.

:: only works for namespaces (and namespace aliases), while .. works for both namespaces and subclasses. Most places where you'd need it you'd be better off using a different name instead, but that isn't always an option.

global:: is a special case that's most often seen in auto-generated code - it resets the referenced namespace to the root.

For instance, suppose you auto-generate some code (maybe for a forms app, EF, or similar) and your app uses the namespace YourCompany.Application. Now one of your customers (using your auto-generation) decides to add their own namespace in their app TheirCompany.YourCompany.Application. Now all your auto code fails because when it compiles .Net doesn't know whether to use your namespace or theirs.

To fix this generate code with global::YourCompany.Application, then those that use your auto-generator can use whatever namespace they like and not conflict.

I think Microsoft added global:: because they expected some .Net customers to add namespaces like System.

Does a namespace alias change linkage?

If you are using different namespaces for foo, then you introduce two different variables, i.e. a_ns::foo and b_ns::foo. Hence, there is no ambiguity, no conflict, and no undefined behaviour - just two different variables just as if you called the one foo and the other bar.

A namespace alias, even at global scope, does not introduce an ambiguity with other translation units, whereas a duplicate namespace-name would. Confer namespace aliases in this online c++ standard draft), which defines uniqueness for namespace-names within the program, but uniqueness for namespace aliases only within a declarative region:

7.3.2 Namespace alias

A namespace-name or namespace-alias shall not be declared as the name
of any other entity in the same declarative region. A namespace-name
defined at global scope shall not be declared as the name of any other
entity in any global scope of the program. ...

Hence, a namespace alias namespace ns=a_ns introduced in a.cpp will be "visible" only in a.cpp, and namespace ns=b_ns introduced in b.cpp will be "visible" only in b.cpp. So each use of ns::foo will unambiguously refer to a_ns in a.cpp and b_ns in b.cpp, respectively.

But if you actually define the same namespace for foo in two different translation units, e.g. namespace ns { int foo; } in both a.cpp and b.cpp, each individual .cpp-file will be compiled correctly, but you will get a linker error, e.g. duplicate symbol __ZN2ns3fooE in: ../a.o; ../b.o.

several alias namespaces in if-statement

The namespace alias that you define is meant for telling the compiler which namespace to use when looking up for symbols at compile time.

What's the problem ?

So when you write

   if(dim == 1) {
namespace poissonProblem = poissonProblem1D;
}

you just define a namespace alias for the if-bloc. It's forgotten as soon as you leave the block.

You should not think that the namespace alias is something dynamic that could be changed in the sequence of your program.

Why is it so ?

Imagine:

namespace poissonProblem1D { 
class X {
public:
X(int c) {} // constructor only with int parameter
virtual ~X() {} // virtual destructor
}; // only a constructor with int is allowed
}

namespace poissonProblem2D {
class X {
public:
X() {} // only constructor without argument
~X() {} // non virtual destructor
}; // only a constructor with int is allowed
}

Suppose now that you could redefine the namespace in the flow of execution as you desired, and that the execution of if-blocks could alter the the namespace alias. How could the compiler then compile the statement:

poissonProblem::X  x(2);  

We have two types poissonProblem1D::X and poissonProblem2D::X, but the compiler wouldn't know at compile time which one to use, which are the valid or invalid parameters and how to generate code for the destruction of the object x.

C++ has strong compile-time type checking which makes dynamic namespace alias impossible.

Edit: How to solve it ?

It depends on the context. Kerek already showed a template based approach.

Another approach is to use conditional compilation. This can prove useful for configuring the the namespace at compilation time (for example choose to use a boost or a std version of a class such as regex).

#define dim 2
#if dim==2
namespace poissonProblem = poissonProblem2D;
#elif dim==1
namespace poissonProblem = poissonProblem1D;
#elif dim==3
namespace poissonProblem = poissonProblem3D;
#endif

C# namespace alias - what's the point?

That is a type alias, not a namespace alias; it is useful to disambiguate - for example, against:

using WinformTimer = System.Windows.Forms.Timer;
using ThreadingTimer = System.Threading.Timer;

(ps: thanks for the choice of Timer ;-p)

Otherwise, if you use both System.Windows.Forms.Timer and System.Timers.Timer in the same file you'd have to keep giving the full names (since Timer could be confusing).

It also plays a part with extern aliases for using types with the same fully-qualified type name from different assemblies - rare, but useful to be supported.


Actually, I can see another use: when you want quick access to a type, but don't want to use a regular using because you can't import some conflicting extension methods... a bit convoluted, but... here's an example...

namespace RealCode {
//using Foo; // can't use this - it breaks DoSomething
using Handy = Foo.Handy;
using Bar;
static class Program {
static void Main() {
Handy h = new Handy(); // prove available
string test = "abc";
test.DoSomething(); // prove available
}
}
}
namespace Foo {
static class TypeOne {
public static void DoSomething(this string value) { }
}
class Handy {}
}
namespace Bar {
static class TypeTwo {
public static void DoSomething(this string value) { }
}
}

C++ namespace alias in entire class scope

Namespace alias in the class definition is illegal, as specified by the language specification.

Its allowed in only in namespace scope or function scope.

You can make alias at namespace scope. But that will be make permanent alias which can be used from other files as well. But the solution is simple : you can use unnamed namespace to prevent alias (and therefore all symbols from the big namespace) from being visible from other files. This is how it can be done:

//MyFile.cpp
namespace myspace
{
namespace //this is unnamed namespace
{
namespace abc = a_big_namespace;
}
struct MyClass
{
void fn()
{
abc::test(); //don't worry, this will work!
}
};
}

//OtherFile.cpp

myspace::abc::test(); //error - that means, prevention worked.

The alias is not visible from other files. When compiling OtherFile.cpp, GCC (4.5.0) says,

'myspace::abc' has not been declared

That proves the alias abc is visible only in MyFile.cpp. Thanks to unnamed namespace.

Demo : http://www.ideone.com/2zyNI (though it doesn't demonstrate OtherFile concept. I cannot have more than one file at ideone.com)



Related Topics



Leave a reply



Submit