On Programming

A discussion of programming strategies and results

Don't Pollute the Global Namespace

| Comments

As projects grow bigger, name collisions become a hazard. Back in the old C days they had a static keyword that would restrict access to the function or variable to the file it was created in. This made is unaccessible to extern and allowed global variables of the same name to exist in other files. This can be a slight bit confusing since static variables in C++ mean that the value of the variable persists through multiple function calls or through multiple instances of a class, but luckily the C-style static keyword is deprecated.

In C++ to restrict variables to only be accessible from within the current file you simply need to create an unnamed namespace. To demonstrate this I created a file named child.cpp

child.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  #include <iostream>

  using namespace std;

  namespace
  {
      void internal_function()
      {
          cout << "child: internal_function\n";
      }
  }

  void external_function()
  {
      cout << "child: external_function\n";
      internal_function();
  }
In this file, internal_function() is only accessible from within child.cpp.

Now I can drive this function with a main.cpp which can have its own internal_function() without naming conflicts!

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  #include <iostream>

  using namespace std;

  void external_function();

  void internal_function()
  {
      cout << "main: internal_function\n";
  }

  int main(int argc, char** argv)
  {
      internal_function();
      external_function();
  }
Compiling this and running it I get:
1
2
3
4
5
6
  $ $CXX main.cpp child.cpp
  $ ./a.out
  main: internal_function
  child: external_function
  child: internal_function
  $ 
Now, just to prove that the unnamed namespace is required, let’s remove it. Heres the new child.cpp:
child.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  #include <iostream>

  using namespace std;

  void internal_function()
  {
      cout << "child: internal_function\n";
  }

  void external_function()
  {
      cout << "child: external_function\n";
      internal_function();
  }
And when I compile it:
1
2
3
4
5
6
  $ $CXX main.cpp child.cpp
  ~/AppData/Local/Temp/child-688096.o:fake:(.text+0x50): multiple definition of `internal_function()'
  ~/AppData/Local/Temp/main-688094.o:fake:(.text+0x50): first defined here
  collect2: ld returned 1 exit status
  clang++: error: linker (via gcc) command failed with exit code 1 (use -v to see invocation)
  $ 
So wrap everything that doesn’t need to be accessed externally in unnamed namespaces to save some headaches down the road!

Comments