Contents

Namespaces

Introduction to Namespaces in C++

A namespace in C++ provides a context where you can declare identifiers such as variables, methods, and classes. It helps in organizing code and avoiding name collisions. For instance, if your code has a function named xyz() and a library also has a function with the same name, the compiler will not be able to distinguish between the two without namespaces. A namespace helps resolve this issue by adding context to the function, class, or variable name.

A namespace essentially defines a scope, and one of its major benefits is preventing name collisions. A well-known example is the std namespace in the C++ Standard Library, where various classes, methods, and templates are defined. While coding in C++, we commonly use using namespace std; to access these elements without needing to prefix std:: to each function call or variable access.

Defining a Namespace

To declare a namespace, use the namespace keyword followed by the namespace name:

				
					namespace my_namespace {
    int variable;
    void function();
    class MyClass {};
}

				
			

No semicolon is needed after the closing brace of a namespace definition. To access elements within the namespace, use the following syntax:

				
					my_namespace::variable;
my_namespace::function();
				
			
Using the using Directive

The using directive allows you to avoid specifying the namespace every time you use a variable or function. By writing using namespace my_namespace;, you tell the compiler that all identifiers in the code are from the given namespace.

				
					#include <iostream>
using namespace std;

namespace first_space {
    void func() {
        cout << "Inside first_space" << endl;
    }
}

namespace second_space {
    void func() {
        cout << "Inside second_space" << endl;
    }
}

using namespace first_space;

int main() {
    func();  // This calls the function from first_space
    return 0;
}

				
			

Output:

				
					Inside first_space
				
			

The using directive applies from the point where it’s used until the end of the scope. If another entity with the same name exists in a broader scope, it gets hidden.

Nested Namespaces

Namespaces can also be nested, where one namespace is defined within another. For example:

				
					namespace outer {
    namespace inner {
        void func() {
            std::cout << "Inside inner namespace" << std::endl;
        }
    }
}

				
			

Output:

				
					Inside second_space
				
			
Scope of Entities in a Namespace

Entities, such as variables and functions, defined in a namespace are scoped within that namespace. This means you can have entities with the same name in different namespaces without causing errors.

				
					#include <iostream>
using namespace std;

namespace first_space {
    void func() {
        cout << "Inside first_space" << endl;
    }
}

namespace second_space {
    void func() {
        cout << "Inside second_space" << endl;
    }
}

int main() {
    first_space::func();  // Calls function from first_space
    second_space::func();  // Calls function from second_space
    return 0;
}

				
			

Output:

				
					Inside first_space
Inside second_space

				
			
Namespaces in Practice

Consider the following code that demonstrates the error caused by using two variables with the same name in the same scope:

				
					int main() {
    int value;
    value = 0;
    double value;  // Error: redeclaration of 'value'
    value = 0.0;
}
				
			

Error:

				
					Compiler Error: 'value' has a previous declaration as 'int value'
				
			

With namespaces, you can declare two variables with the same name in different namespaces without conflict:

				
					#include <iostream>
using namespace std;

namespace first_space {
    int val = 500;
}

int val = 100;

int main() {
    int val = 200;
    cout << first_space::val << endl;
    return 0;
}

				
			

Output:

				
					ns::Geek::display()
				
			

Alternatively, a class can be declared inside a namespace and defined outside the namespace:

				
					#include <iostream>
using namespace std;

namespace ns {
    class Geek;
}

class ns::Geek {
public:
    void display() {
        cout << "ns::Geek::display()" << endl;
    }
};

int main() {
    ns::Geek obj;
    obj.display();
    return 0;
}

				
			

Output:

				
					ns::Geek::display()
				
			

Namespaces in C++ (Set 2: Extending and Unnamed Namespaces)

Defining a Namespace:

A namespace definition in C++ starts with the namespace keyword followed by the name of the namespace, like so:

				
					namespace my_namespace 
{
    // Variable declarations
    int my_var;

    // Method declarations
    void my_function();

    // Class declarations
    class MyClass {};
}

				
			

Note that there is no semicolon after the closing brace of the namespace definition. To use variables or functions from a specific namespace, prepend the namespace name with the scope resolution operator (::), like this:

				
					my_namespace::my_var;
my_namespace::my_function();

				
			
The using Directive:

To avoid manually prepending the namespace name each time, you can use the using namespace directive. This tells the compiler to implicitly use the names from the specified namespace:

				
					#include <iostream>
using namespace std;

// Define namespaces
namespace first_space
{
    void func() 
    {
        cout << "Inside first_space" << endl;
    }
}

namespace second_space
{
    void func() 
    {
        cout << "Inside second_space" << endl;
    }
}

using namespace first_space;

int main() 
{
    func();  // Calls the function from first_space
    return 0;
}

				
			

The names introduced by the using directive follow normal scoping rules. Once introduced, they are visible from the point of the directive to the end of the scope where it was used.

Nested Namespaces:

You can also define namespaces within other namespaces, referred to as nested namespaces:

				
					namespace outer_space 
{
    namespace inner_space 
    {
        void func() 
        {
            // Function inside inner_space
        }
    }
}

				
			

To access members of a nested namespace, use the following syntax:

				
					using namespace outer_space::inner_space;

				
			

If you only use outer_space, it will also make the inner namespace available in scope:

				
					#include <iostream>
using namespace std;

namespace outer_space
{
    void outer_func() 
    {
        cout << "Inside outer_space" << endl;
    }

    namespace inner_space
    {
        void inner_func() 
        {
            cout << "Inside inner_space" << endl;
        }
    }
}

using namespace outer_space::inner_space;

int main() 
{
    inner_func();  // Calls function from inner_space
    return 0;
}

				
			
Creating Multiple Namespaces:

It’s possible to create multiple namespaces with different names in the global scope. Here’s an example:

				
					#include <iostream>
using namespace std;

// First namespace
namespace first
{
    int func() { return 5; }
}

// Second namespace
namespace second
{
    int func() { return 10; }
}

int main() 
{
    cout << first::func() << endl;   // Calls func() from first namespace
    cout << second::func() << endl;  // Calls func() from second namespace
    return 0;
}

				
			

Output:

				
					5
10
				
			
Extending Namespaces:

It is possible to define a namespace in parts using the same name more than once. Essentially, the second block is an extension of the first:

				
					#include <iostream>
using namespace std;

namespace first 
{ 
    int val1 = 500;  
}

namespace first 
{ 
    int val2 = 501;  
}

int main() 
{
    cout << first::val1 << endl;  // Accesses first part of the namespace
    cout << first::val2 << endl;  // Accesses second part of the namespace
    return 0;
}

				
			

Output:

				
					500
501
				
			
Unnamed Namespaces:

Unnamed namespaces allow you to define identifiers that are unique to the file they are declared in. They can be seen as a replacement for the old static keyword for file-scope variables. In unnamed namespaces, no namespace name is provided, and the compiler generates a unique name for it:

				
					#include <iostream>
using namespace std;

namespace 
{
    int rel = 300;
}

int main() 
{
    cout << rel << endl;  // Prints 300
    return 0;
}

				
			

Output:

				
					300
				
			

Namespace in C++ | Set 3 (Accessing, creating header, nesting and aliasing)

Different Ways to Access Namespaces in C++

In C++, there are multiple ways to access variables and functions within a namespace. Here’s an explanation with modified examples.

Defining a Namespace

A namespace definition starts with the namespace keyword followed by the name of the namespace, as shown below:

				
					namespace my_namespace 
{
    // Variable declaration
    int my_var;

    // Function declaration
    void my_function();

    // Class declaration
    class MyClass {};
}

				
			

There is no semicolon after the closing brace. To access variables or functions from the namespace, use the following syntax:

				
					my_namespace::my_var;     // Access variable
my_namespace::my_function();  // Access function

				
			
The using Directive

To avoid repeatedly writing the namespace name, you can use the using namespace directive. This informs the compiler to assume that all names used after the directive come from the specified namespace:

				
					#include <iostream>
using namespace std;

// First namespace
namespace first_ns
{
    void display()
    {
        cout << "Inside first_ns" << endl;
    }
}

// Second namespace
namespace second_ns
{
    void display()
    {
        cout << "Inside second_ns" << endl;
    }
}

using namespace first_ns;

int main()
{
    display();  // Calls the function from first_ns
    return 0;
}

				
			

In this case, the function from first_ns will be called because of the using directive.

Nested Namespaces

Namespaces can be nested, meaning you can define one namespace inside another:

				
					namespace outer_ns
{
    void outer_function() {}

    namespace inner_ns
    {
        void inner_function() {}
    }
}

				
			

You can access members of a nested namespace using the following syntax:

				
					using namespace outer_ns::inner_ns;
				
			

Alternatively, you can also use a more hierarchical approach:

				
					#include <iostream>
using namespace std;

// Outer namespace
namespace outer_ns
{
    void outer_function() 
    {
        cout << "Inside outer_ns" << endl;
    }

    // Inner namespace
    namespace inner_ns
    {
        void inner_function()
        {
            cout << "Inside inner_ns" << endl;
        }
    }
}

using namespace outer_ns::inner_ns;

int main()
{
    inner_function();  // Calls the function from inner_ns
    return 0;
}

				
			
Accessing Namespace Members

1. Accessing Normally : You can access members of a namespace using the scope resolution operator (::)

				
					#include <iostream>
using namespace std;

namespace sample_ns
{
    int number = 100;
}

int main()
{
    cout << sample_ns::number << endl;  // Accesses variable with scope resolution
    return 0;
}

				
			

Output:

				
					100
				
			

2. Using the using Directive : You can also use the using directive to make variables and functions directly accessible:

				
					#include <iostream>
using namespace std;

namespace sample_ns
{
    int number = 100;
}

// Use of 'using' directive
using namespace sample_ns;

int main()
{
    cout << number << endl;  // Accesses variable without scope resolution
    return 0;
}

				
			

Example:

				
					100
				
			
Using Namespaces Across Files

Namespaces can be defined in one file and accessed from another. This can be done as follows:

File 1 (header file):

				
					// file1.h
namespace sample_ns
{
    int getValue() 
    {
        return 50;
    }
}

				
			

File 2 (source file):

				
					// file2.cpp
#include <iostream>
#include "file1.h"  // Including file1.h
using namespace std;

int main()
{
    cout << sample_ns::getValue();  // Accessing function from file1.h
    return 0;
}

				
			

This allows the function declared in file1.h to be used in file2.cpp.

Nested Namespaces

In C++, namespaces can also be nested, meaning one namespace can be declared inside another:

				
					#include <iostream>
using namespace std;

// Outer namespace
namespace outer_ns
{
    int value = 10;
    namespace inner_ns
    {
        int inner_value = value;  // Access outer_ns::value
    }
}

int main()
{
    cout << outer_ns::inner_ns::inner_value << endl;  // Outputs 10
    return 0;
}

				
			

Output:

				
					10
				
			
Namespace Aliasing

You can create an alias for a namespace to simplify its usage. The syntax for aliasing is as follows:

				
					#include <iostream>

namespace long_name_space
{
    namespace nested_space
    {
        namespace deep_space
        {
            int data = 99;
        }
    }
}

// Alias for nested namespaces
namespace short_name = long_name_space::nested_space::deep_space;

int main()
{
    std::cout << short_name::data << std::endl;  // Access data using alias
    return 0;
}

				
			

Output:

				
					99