Search

2.9 — Naming collisions and an introduction to namespaces

Let’s say you are driving to a friend’s house for the first time, and the address given to you is 245 Front Street in Mill City. Upon reaching Mill City, you pull up your map, only to discover that Mill City actually has two different Front Streets across town from each other! Which one would you go to? Unless there were some additional clue to help you decide (e.g. you remember his house is near the river) you’d have to call your friend and ask for more information. Because this would be confusing and inefficient (particularly for your mailman), in most countries, all street names and house addresses within a city are required to be unique.

Similarly, C++ requires that all identifiers be non-ambiguous. If two identical identifiers are introduced into the same program in a way that the compiler or linker can’t tell them apart, the compiler or linker will produce an error. This error is generally referred to as a naming collision (or naming conflict).

An example of a naming collision

a.cpp:

main.cpp:

When the compiler compiles this program, it will compile a.cpp and main.cpp independently, and each file will compile with no problems.

However, when the linker executes, it will link all the definitions in a.cpp and main.cpp together, and discover conflicting definitions for function myFcn. The linker will then abort with an error. Note that this error occurs even though myFcn is never called!

Most naming collisions occur in two cases:
1) Two (or more) definitions for a function (or global variable) are introduced into separate files that are compiled into the same program. This will result in a linker error, as shown above.
2) Two (or more) definitions for a function (or global variable) are introduced into the same file (often via an #include). This will result in a compiler error.

As programs get larger and use more identifiers, the odds of a naming collision being introduced increases significantly. The good news is that C++ provides plenty of mechanisms for avoiding naming collisions. Local scope, which keeps local variables defined inside functions from conflicting with each other, is one such mechanism. But local scope doesn’t work for functions names. So how do we keep function names from conflicting with each other?

What is a namespace?

Back to our address analogy for a moment, having two Front Streets was only problematic because those streets existed within the same city. On the other hand, if you had to deliver mail to two addresses, one at 209 Front Street in Mill City, and another address at 417 Front Street in Jonesville, there would be no confusion about where to go. Put another way, cities provide groupings that allow us to disambiguate addresses that might otherwise conflict with each other. Namespaces act like the cities do in this analogy.

A namespace is a region that allows you to declare names inside of it for the purpose of disambiguation. The namespace provides a scope (called namespace scope) to the names declared inside of it -- which simply means that any name declared inside the namespace won’t be mistaken for identical names in other scopes.

Key insight

A name declared in a namespace won’t be mistaken for an identical name declared in another scope.

Within a namespace, all names must be unique, otherwise a naming collision will result.

Namespaces are often used to group related identifiers in a large project to help ensure they don’t inadvertently collide with other identifiers. For example, if you put all your math functions in a namespace called math, then your math functions won’t collide with identically named functions outside the math namespace.

We’ll talk about how to create your own namespaces in a future lesson.

The global namespace

In C++, any name that is not defined inside a class, function, or a namespace is considered to be part of an implicitly defined namespace called the global namespace (sometimes also called the global scope).

In the example at the top of the lesson, functions main() and both versions of myFcn() are defined inside the global namespace. The naming collision encountered in the example happens because both versions of myFcn() end up inside the global namespace, which violates the rule that all names in the namespace must be unique.

The std namespace

When C++ was originally designed, all of the identifiers in the C++ standard library (including std::cin and std::cout) were available to be used without the std:: prefix (they were part of the global namespace). However, this meant that any identifier in the standard library could potentially conflict with any name you picked for your own identifiers (also defined in the global namespace). Code that was working might suddenly have a naming conflict when you #included a new file from the standard library. Or worse, programs that would compile under one version of C++ might not compile under a future version of C++, as new identifiers introduced into the standard library could have a naming conflict with already written code. So C++ moved all of the functionality in the standard library into a namespace named “std” (short for standard).

It turns out that std::cout‘s name isn’t really std::cout. It’s actually just cout, and std is the name of the namespace that identifier cout is part of. Because cout is defined in the std namespace, the name cout won’t conflict with any objects or functions named cout that we create in the global namespace.

Similarly, when accessing an identifier that is defined in a namespace (e.g. std::cout) , you need to tell the compiler that we’re looking for an identifier defined inside the namespace (std).

Key insight

When you use an identifier that is defined inside a namespace (such as the std namespace), you have to tell the compiler that the identifier lives inside the namespace.

There are a few different ways to do this.

Explicit namespace qualifier std::

The most straightforward way to tell the compiler that we want to use cout from the std namespace is by explicitly using the std:: prefix. For example:

The :: symbol is an operator called the scope resolution operator. The identifier to the left of the :: symbol identifies the namespace that the name to the right of the :: symbol is contained within. If no identifier to the left of the :: symbol is provided, the global namespace is assumed.

So when we say std::cout, we’re saying “the cout that lives in namespace std“.

This is the safest way to use cout, because there’s no ambiguity about which cout we’re referencing (the one in the std namespace).

Best practice

Use explicit namespace prefixes to access identifiers defined in a namespace.

Using namespace std (and why to avoid it)

Another way to access identifiers inside a namespace is to use a using directive statement. Here’s our original “Hello world” program with a using directive:

A using directive tells the compiler to check a specified namespace when trying to resolve an identifier that has no namespace prefix. So in the above example, when the compiler goes to determine what identifier cout is, it will check both locally (where it is undefined) and in the std namespace (where it will match to std::cout).

Many texts, tutorials, and even some compilers recommend or use a using directive at the top of the program. However, used in this way, this is a bad practice, and highly discouraged.

Consider the following program:

The above program doesn’t compile, because the compiler now can’t tell whether we want the cout function that we defined, or the cout that is defined inside the std namespace.

When using a using directive in this manner, any identifier we define may conflict with any identically named identifier in the std namespace. Even worse, while an identifier name may not conflict today, it may conflict with new identifiers added to the std namespace in future language revisions. This was the whole point of moving all of the identifiers in the standard library into the std namespace in the first place!

Warning

Avoid using directives (such as using namespace std;) at the top of your program. They violate the reason why namespaces were added in the first place.

We’ll talk more about using statements (and how to use them responsibly) in lesson 6.12 -- Using statements.


2.10 -- Introduction to the preprocessor
Index
2.8 -- Programs with multiple code files

107 comments to 2.9 — Naming collisions and an introduction to namespaces

  • Jim177

    Hey, I ran the first program to use main.cpp and a.cpp. The program compiled and I didn't get any output in the console window.  

    However the project did abort in the build log. (C::B 20.3)

    This may be a dumb question, but how do we know that the linker did the aborting. I didn't see any wording to that effect in the build log. Is there someplace else the linkers error shows on C::B?

  • Auto

    Just don't use same function names 4Heed

  • Zuhail

    Hey as the scope is a compile time property if i do something like this for the first given example  : (assuming I've already added necessary Header file and main function in main file)
    1)a.cpp
    static void func(){
    //Does nothing
    }
    2)main.cpp
    void func(){
    //Also does nothing
    }

    Will this work as each file is compiled individually and function in a.cpp has file scope so this shouldn't result in naming conflict right?
    P.S. sorry for not using code tags mobile browser has some issues with the website

  • Math

    Hello
    Thank you for the amazing amazing tutorials you provide. I was wondering if you have tutorials like these for other topic?

  • Mint

    Is it okay to use the "using" directive to access specific names from the std namespace?

    For example:

  • Confused on global namespace scope

    Here, you said the compiler can’t tell whether we want the cout function that we defined, or the cout that is defined inside the std namespace.

    I have a questions:
    We have main() and cout() functions which are defined inside a global namespace scope. So, cout(library) is defined inside a local scope of main(), while the function cout() lives in a global namespace, why there would be any conflict here?
    They are defined in two different scopes?

    • nascardriver

      > cout(library) is defined inside a local scope of main(),
      `cout` is a variable, it's defined in the `std` namespace, which you merged with the global namespace by `using namespace std;`.

      • sami

        When I removed "using namespace std", then I didn't get any error! WoW! That's amazing! Thank you SO SO much!

        Here, the following code violates the second rule of ODR (2. Within a given program, an object or normal function can only have one definition. ), I was wondering why this program is compiled and linked properly without giving any error?! Here there are two definitions for "cout", one in library, one in a.cpp.

        • nascardriver

          One is `basic_ostream cout` in the `std::namespace`, the other is `int cout()` in the global namespace. They have different names (Because of the namespace), and different types. If you try to add another `int cout()` to main.cpp, you'll get an error.

    • Somto

      Actually cout(library) is NOT defined inside a local scope of main(). It was just "called" there. It is defined in the "iostream" library which you added to your global namespace when you specified "#include <iostream>"

  • any name you picked

    1) "...this meant that any identifier in the standard library could potentially conflict with any name you picked for your own identifiers..."

    Shouldn't this sentence be written as?It is kind of implied that any name!

    this meant that any identifier in the standard library could potentially conflict with any name you picked, that has the same name as standard library's, for your own identifiers

    2) "It turns out that std::cout's name isn’t really std::cout. It’s actually just cout, and std is the name of the namespace that identifier cout is part of. Because cout is defined in the std namespace, the name cout won’t conflict with any objects or functions named cout that we create in the global namespace ."

    I think the above statement correct if this statement is added at the end "as long as we use std:: as prefix"; otherwise, we could have a identifier named "cout" in out program which conflicts with cout library!

  • Robbas

    Hello, I looked at this example but I'm confused as to why we shouldn't use "using namespace".

    We get a compile error anyway even without the namespace, because you said in the previous lessons that we can't use a keyword for an identifier. So looking at the example, using namespace is safe as long as you don't use keywords as identifiers which is something we won't do anyway. Can you help me understand this please? Thank you

    • nascardriver

      This point is that the following code works:

      Later, you decide to add a function to your code, you call it "cout"

      There's nothing wrong with each of these snippets in particular. Note that it doesn't have to be you who added the `cout` function, it could come from a library too.

      When you combine the two codes, ie. add `cout` to the program, problems arise. These problems are unnecessary and could have been avoided by not `using namespace`.

  • Bhargava

    Can't you at least just do

    ... most people aren't going to be declaring their own namespace with cout. Much better than typing std::cout<< all the time

    • nascardriver

      It doesn't have to be you who defines another entity with the same name as on in a library. The `std` library itself has entities that collide with standard functions (eg. `std::min` vs `min`).
      Using `using std::cout` is better than `using` the entire namespace, but should be avoided still. If you know that the entity you're `using` doesn't collide with anything, you can add a `using` directive for it, but don't do so at file-scope. Add the `using` directive inside the function you're accessing the entity in.

  • Mark

    "and" Jonesville should read "in" Jonesville. Also, thanks for this website, it's the only programming course that I've managed to stick with so far.

  • salah

    Amazing tutorial do you have another tutorial like : data structure?

  • slate

    However, when the linker executes, it will link all the definitions in a.cpp and main.cpp together, and discover conflicting definitions for function myFcn. The linker will then abort with an error. Note that this error occurs even though myFcn is never called!

    but in other lessons you say that compiler dont look what is int the other files so why its make error

  • cas

    This tutorial is amazing

  • Omran

    bro this is an amazing tutorial , i'm actually enjoying it and also clicking on every ad to support it thanks a lot guys :)

  • Sam

    "A namespace is a region that allows you to declared names inside of it for the purpose of disambiguation"

    Grammatical error. Change "declared" to "declare"!

    Merry Christmas!

  • koe

    "There are a few different ways to do this."

    Only two are mentioned here, better to say:
    "There are a couple ways to do this."
    or
    "There are a few different ways to do this. We will highlight two here, the other methods (?) are bad (?)."

  • Nirbhay

    Hello Alex!

    I would be thankful if you can find a way to show the readers which part of the tutorial is updated or which new content is added. I went through this tutorial quite some time ago and now I do not know what to look for in this update. :)

    Thanks

  • Vai

    "Avoid using directives (such as using namespace std;) at the top of your program. They violate the reason why namespaces were added in the first place." then why "using namespace" was introduced? When will it be useful?

    • The rule isn't "never use", it's "avoid". There are cases in which `using namespace` is useful. If you know that your libraries are compatible with each other (`std` isn't even compatible with other parts of C++, so don't use `using namespace std;` unless it's in a small scope), you can use `using namespace`.

    • Alex

      It can still be useful when used inside a smaller scope, such as a function.

      • Nirbhay

        @Alex please explain it with an example..why can it be used inside a smaller scope, such as a function?

        • nascardriver

          Using `using namespace` in a function limits the scope that's affected by the `using` directive. Anyone reading the function should be able to see the directive and write code accordingly. If the directive was at file-scope, it's easy to miss.

          I'll use `chrono` for an example of a `using` directive. It doesn't make sense for `std`.

          As you can see, it makes sense `using namespace` in this case, as the code without it is a lot longer and not as easy to read.
          If we used the namespace at file-scope, we wouldn't be able to user other user-defined literals anymore.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]