Like it!

Join us on Facebook!

Like it!

C++ namespaces with private members

A cool alternative to the C way of having static global variables.

In C++ you can build beautiful namespaces with private members (variables and functions). This is a good choice when you want to hide the inner workings of a set of utility functions from the final user. You can accomplish that thanks to the concept of anonymous namespaces. An anonymous namespace is a namespace without name, like the following one:

namespace
{
    // your stuff here
}

The beauty of anonymous namespaces is that they are available only in their translation unit, that is the .cpp file they are located.

For example, say I'm working on a small namespace called thing. This is the header file:

// thing.hpp

namespace thing
{
    int getX();
    int getSum();
}

And this is the implementation file:

// thing.cpp

namespace thing
{
    namespace   // anonymous namespace
    {
        int x = 1;
        int y = 2;

        int sum(int a, int b)
        {
            return a + b;
        }
    }

    int getX() 
    {
        return x;
    }

    int getSum()
    {
        return sum(x, y);
    }
};

Notice how I've wrapped the private members in the anonymous namespace. Now only thing can access x, y and sum(). If you try to touch those variables from the outside, an error occurs. Let's try:

#include <cstdio>
#include "thing.hpp"

int main(int argc, char **argv)
{
    printf("%d\n", thing::getX());     // OK
    printf("%d\n", thing::getSum());   // OK
    printf("%d\n", thing::sum(1, 2));  // error: ‘sum‘ is not a member of ‘thing’    
    printf("%d\n", thing::y);          // error: ‘y‘ is not a member of ‘thing’    
}

Sources

Stackoverflow - Why are unnamed namespaces used and what are their benefits? (link)
Wikipedia - Translation unit (link)

comments
Roy on June 17, 2018 at 14:05
Exactly what I needed. Thanks!
Adrian on April 08, 2019 at 15:10
I hope you read this: there's an error on the wikipedia article link (you need to close your parenthesis).
Triangles on April 08, 2019 at 18:35
@Adrian thanks for the feedback, link fixed!
Dan on April 19, 2019 at 22:02
This doesn't seem to work. After testing, I can still access the members in the main file.
maisonsmd on April 28, 2019 at 07:48
Me also, I'm still able to access those member.
D on May 18, 2019 at 20:33
I copy-pasted into repl.it (C++11), and I could still access everything. The StackOverflow link had the same effect.
Triangles on June 03, 2019 at 12:18
@D and others: my wild guess is that this trick works only when you have actual .o files generated by your compiler.
Xiao sings on June 12, 2019 at 06:30
Thanks a lot, dude :)
S on July 07, 2019 at 21:20
I've just tested this with the Microsoft Visual Studio compiler and it didn't let me access anything inside the anonymous namespace.
Dave Smith on July 27, 2019 at 19:48
Thanks, @Triangles, this is very useful! This works for me on Ubuntu 16.04 using g++ 5.4.0. Only minor correction I noticed: your second #include in main should be of "thing.hpp".
Triangles on August 02, 2019 at 12:45
@Dave Smith good catch! Typo fixed. Thank you :)
Karol on April 16, 2020 at 10:44
This looks neat, but doesn't apply to code written in C++11 or later. As stated here: https://en.cppreference.com/w/cpp/language/namespace#Unnamed_namespaces

"Unnamed namespaces as well as all namespaces declared directly or indirectly within an unnamed namespace have internal linkage, which means that any name that is declared within an unnamed namespace has internal linkage." - so basically whether a name is declared inside an anonymous namespace or not, it is still available throughout the translation unit.
Kecomi on October 10, 2020 at 05:35
When using Xcode and naming the internal namespace, I noticed that the function doesn't show up in auto-complete. It's not totally hidden or inaccessible though, in that if you type in the name of the internal namespace then it will show up in auto complete