Namespace (C++)

https://www.geeksforgeeks.org/namespace-in-c/

A namespace defines a scope in which we can declare or define variables, methods, and classes.

using namespace std;
  • this is actually really bad in practice

Why do we even need namespaces?

To prevent name collisions.

Consider the std library, which has a string. Now, you might use std::string, or you might want to use your own string implementation, ex: robotics::string. Without namespaces, one would be string, the other could be RoboticsString, but the alternative is to provide namespaces to avoid this.

Resources

Ooh, there even is a connection to Multiple Inheritance, where you saw you can access member variables using d.B::a.

No need to indent namespaces

Usually, for readability, we indent our code after using a tab. But no need for namespaces.

Basic Namespace Usage

#include <iostream>
 
namespace example
{
  void dummy() { std::cout << "Dummy\n"; }
}
 
namespace buzz
{
  void test() { example::dummy(); }
}
 
int main()
{
  buzz::test();
}
namespace n1 {
namespace n2 {
    // code declarations
	void f1():
}
}
 
using namespace n1::n2;
 
void f2() {
    f1();
}

But using namespace is bad because the whole point of having namespaces is so that it is clear where this function call is coming from.

namespace n1 {
void f2() {
    n2::f1();
}
}
 

Nested Namespace

During my time at NVIDIA, I saw layers of namespaces being used. It wasn’t clear to me how namespaces actually work.

https://medium.com/swlh/all-about-namespaces-fa9a597ed0d4

I am confused on access

What if you are inside namespace n2, and want to call functions defined from inside namespace n1?

Ahhh, it’s important that you understand scopes and scope resolution.

Scope of namespaces

In C++, the scope of a namespace extends throughout the entire program. When you declare multiple namespaces with the same name, their members are effectively merged. This is called namespace extension.

In simple terms, this means that you can access all parent namespaces.

Consider the following example:

#include <iostream>
 
namespace A {
namespace B {
void hello() { std::cout << "hello world";}
namespace C {
    void test() {
        hello(); // allowed
        /* Any of these would also work:
        B::hello();
        A::B::hello();
        ::A::B::hello();
        */
    }
}
}
}
  • When test() tries to call hello(), it first tries to call it from its current
  1. ::A::B::C::hello() →does not work
  2. A::B::hello() → works!

Any of the following instead of hello() would also work.

Consider this following example:

#include <iostream>
namespace A {
namespace D {
    void hello() { std::cout << "hello world";}
}
}
namespace A {
namespace B {
namespace C {
    void test() {
        D::hello(); // allowed
        A::D::hello(); // allowed
        ::A::D::hello(); // allowed
        hello(); // NOT allowed
    }
}
}
}
  • Here,you actually don’t have access to namespace D, so if you try calling hello() on its own from within namespace C, it will fail. However, namespace D is accessible from within namespace A, and since C is nested inside namespace A, you simply need to specify namespace D to be able to call the hello() function.

Global Namespace (prepending ::)

This is a small distinction to understand the point of having :: in front, which I saw myself in NVIDIA codebase.

#include <string>
 
// Both of these are correct, but what is the difference?
std::string s;
::std::string s;

The difference is that without the :: in front ( std::string), the resolution is done from the current scope, while having the :: in front makes it search from the root namespace (and thus clearer, the tradeoff is that it is overkill mosttimes) (::std:string)

Here is another example from StackOverflow

namespace A
{
    namespace B
    {
         class C;
    }
}
namespace B
{ 
    class C;
}
namespace A
{
    using B::C; // resolves to A::B::C
    using ::B::C; // resolves to B::C
    // (note that one of those using declarations has to be
    // commented for making this valid code!)
}
 

If you want to access starting from global namespace, you start with ::, something like

namespace n1 {
namespace n2 {
    ::z1::z2::functionCall();
}
}

Anonymous Namespaces

What happens when you use namespace without specifying an actual name? Who can actually use it?

It is only accessible from within the same file. Doesn’t have to be inside the brackets.

  • though it seems that if you include the file, you can use it?

Anonymous Namespaces

Anonymous namespaces are use is to make functions/objects/etc accessible only within that file. It’s almost the same as static in C.

namespace robotics {
namespace calibration {
namespace {
    void doSomething();
}
}
}

In some sense, that isn’t different from declaring a static function, is it?

https://stackoverflow.com/questions/154469/why-should-you-prefer-unnamed-namespaces-over-static-functions