Search

4.3c — Using statements

If you’re using the standard library a lot, typing “std::” before everything you use from the standard library can become repetitive. C++ provides some alternatives to simplify things, called “using statements”.

The using declaration

One way to simplify things is to utilize a using declaration statement.

Here’s our Hello world program again, with a using declaration on line 5:

The using declaration “using std::cout;” tells the compiler that we’re going to be using the object “cout” from the std namespace. So whenever it sees “cout”, it will assume that we mean “std::cout”. If there’s a naming conflict between std::cout and some other use of cout, std::cout will be preferred. Therefore on line 6, we can type “cout” instead of “std::cout”.

This doesn’t save much effort in this trivial example, but if you are using cout a lot inside of a function, a using declaration can make your code more readable. Note that you will need a separate using declaration for each name you use (e.g. one for std::cout, one for std::cin, and one for std::endl).

Although this method is less explicit than using the “std::” prefix, it’s generally considered safe and acceptable.

The using directive

Another way to simplify things is to use a using directive statement. Here’s our Hello world program again, with a using directive on line 5:

The using directive “using namespace std;” tells the compiler that we want to use everything in the std namespace, so if the compiler finds a name it doesn’t recognize, it will check the std namespace. Consequently, when the compiler encounters “cout” (which it won’t recognize), it’ll look in the std namespace and find it there. If there’s a naming conflict between std::cout and some other use of cout, the compiler will flag it as an error (rather than preferring one instance over the other).

For illustrative purposes, let’s take a look at an example where a using directive causes ambiguity:

In the above example, the compiler is unable to determine whether the x in main refers to a::x or b::x. In this case, it will fail to compile with an “ambiguous symbol” error. We could resolve this by removing one of the using statements, or using an explicit a:: or b:: prefix with x.

Here’s another more subtle example:

In the above example, the compiler is unable to determine whether we meant std::cout or the cout function we’ve defined, and again will fail to compile with an “ambiguous symbol” error. Although this example is trivial, if we had explicitly prefixed std::cout like this:

or used a using declaration instead of a using directive:

then our program wouldn’t have any issues in the first place.

Limiting the scope of using declarations and directives

If a using declaration or directive is used within a block, the using statement applies only within that block (it follows normal scoping rules). This is a good thing, as it reduces the chances for naming collisions to occur just within that block. However, many new programmers put using directives into the global scope. This pulls all of the names from the namespace directly into the global scope, greatly increasing the chance for naming collisions to occur. This is considered bad practice.

Rule: Avoid “using” statements outside of a function (in the global scope).

There’s some debate about whether using directives are okay to use within functions, where their impact is limited. However, our take is that using declarations are the better choice if using statements are desired, and that using directives should be avoided entirely.

Suggestion: We recommend you avoid “using directives” entirely.

Cancelling or replacing a using statement

Once a using statement has been declared, there’s no way to cancel or replace it with a different using statement within the scope in which it was declared.

The best you can do is intentionally limit the scope of the using statement from the outset using the block scoping rules.

Of course, all of this headache can be avoided by explicitly using the scope resolution operator (::) in the first place.

4.4 -- Implicit type conversion (coercion)
Index
4.3b -- Namespaces

90 comments to 4.3c — Using statements

  • Suprith

    #include <iostream> // imports the declaration of std::cout

    int cout() // declares our own "cout" function
    {
        return 5;
    }

    int main()
    {
        using namespace std; // makes std::cout accessible as "cout"
        cout << "Hello, world!"; // uh oh!  Which cout do we want here?  The one in the std namespace or the one we defined above?

        return 0;
    }
    My doubt is , in the above example, cout should suppose to resolve to std:cout. Why it'll conflict with int cout().

    • Alex

      Nope. using namespace std tells the compiler "std::cout" should be referenceable as "cout". Thus, when we call "cout", the compiler doesn't know whether we mean std::cout or our own cout function.

      If you want std::cout to take precedence over our own cout inside this function, you should use a using declaration (e.g. using std::cout). Then when the compiler sees cout, it will know that std::cout should take precedence.

      In other words, using declarations (e.g. using std::cout) imply a precedence, using directives (e.g. using namespace std) do not.

  • why

    HII ALEX ,MY doubt is here "cout" means that is in iostream where cout() this is another function .so it wont give compile error.
    #include <iostream> // imports the declaration of std::cout

    int cout() // declares our own "cout" function
    {
        return 5;
    }

    int main()
    {
        using namespace std; // makes std::cout accessible as "cout"
        cout << "Hello, world!"; // uh oh!  Which cout do we want here?  The one in the std namespace or the one we defined above?

        return 0;
    }

    • nascardriver

      Hi why!

      Just try to compile it yourself, it doesn't work. Don't use 'using namespace' and give your functions unique names and you'll be fine.

  • Q

    Hi Alex,

    In the most recent version of Code::Blocks (17.12), the statement using namespace std is standard for every new file or project you create.
    If it really is such bad practice to use a using directive statement with global scope, then why would a IDE like Code::Blocks implement it in its standard template (with global scope)?
    Wouldn't it suffice if I refrain from naming any of my objects after anything in the std library?
    Below an example of the standard piece of code you get every time you create a project:

    On a unrelated note, thanks for the tutorial. It really is one of the best ones out there.
    Cheers.

    • nascardriver

      Hi Q!

      > why would a IDE like Code::Blocks implement it in its standard template (with global scope)?
      I don't know. A lot of IDEs do this. You can change the new project template in Code::Blocks to your liking.

      > Wouldn't it suffice if I refrain from naming any of my objects after anything in the std library?
      You should definitely do this. But how do you know none of the other code you're using was written with naming conflicts in mind? eg. min and max are common names that cause conflicts from time to time.

      • Q

        Hello nascardriver!

        > But how do you know none of the other code you're using was written with naming conflicts in mind? eg. min and max are common names that cause conflicts from time to time.
        This is a very good point, did not think of this.
        I will just use the scope resolution operator or use a using namespace std in block scope if it makes the code more readable.

        Thank you for replying so fast!

        • Alex

          A few thoughts here:
          1) Yes, it really is bad practice to use "using namespace std" in the global scope (it's more okay at function scope if used judiciously, but personally I avoid it altogether). I'm surprised Code::Blocks does this by default, and I'm not sure what the rationale for doing so would be.

          2) While your code might not have a naming conflict now, you can't guarantee it won't with future extensions of the language! So code that compiles today might not compile once you've upgraded your compiler. Using the explicit qualifier avoids these kinds of issues.

          • Q

            Thank you for your reply and clearing this up, no idea why C::B would do this by default either. I'll just be using std:: from now on. Thanks 🙂

Leave a Comment

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