Namespaces

using Declarations

Typing the fully qualified name all the time soon gets boring. After a few calls to Graphics::Color::setRed or Company::Project::Utils::add, the repeated prefixes clutter more than they help. A using declaration allows you to bring one particular name into the current scope so you can use it without the prefix.

The syntax is very simple. You use the using keyword, then the full name of the entity you want, followed by a semicolon.

#include <iostream>

namespace Math
{
    int square(int x)
    {
        return x * x;
    }
}

int main()
{
    using Math::square;

    int result{ square(8) };
    std::cout << "Square is " << result << '\n';
    return 0;
}

Within main, the using Math::square; statement causes the name Math::square to be made visible in the current scope. From that point onwards, the name square can refer to the function Math::square. Consequently, the function call square(8) in the main function can be used without requiring qualification by namespace name, and the value 64 returned by the function is assigned to result. The using declaration causes no copying or moving of the function.

A using declaration can have different extents. If a using declaration occurs at block scope, it remains effective until the end of that block. If it occurs at namespace scope, it remains effective from that point onward within that namespace scope. The program below demonstrates both:

#include <iostream>

namespace Utility
{
    void log(const char* text)
    {
        std::cout << text << '\n';
    }

    int clamp(int value, int low, int high)
    {
        if (value < low)
            return low;

        if (value > high)
            return high;

        return value;
    }
}

using Utility::log;

int main()
{
    log("Starting");

    using Utility::clamp;

    int limited{ clamp(150, 0, 100) };
    std::cout << "Clamped value is " << limited << '\n';
    return 0;
}

The first declaration, using Utility::log;, is at namespace scope, so the name log may be used in main and other declarations that appear later in that scope without the prefix Utility::. The second declaration, using Utility::clamp;, is within main, and so only affects the block in which it appears. Once it appears, the call to clamp(150, 0, 100) calls Utility::clamp, which then returns 100, as 150 is greater than the upper bound.

Same thing applies here. Nested namespaces work the same way. You just write the full path into the using declaration:

#include <iostream>

namespace Graphics
{
    namespace Color
    {
        void setBlue()
        {
            std::cout << "Blue channel set\n";
        }
    }
}

int main()
{
    using Graphics::Color::setBlue;

    setBlue();
    return 0;
}

using Graphics::Color::setBlue; brings the innermost function into the local scope of main. The subsequent call, setBlue(), does not need to be qualified in any way. If you had just written using Graphics::Color;, the code would not compile, because a using declaration has to specify a particular member, not an entire nested namespace.

When a name has been introduced with a using declaration, it becomes available for unqualified lookup in that scope. A name in an outer scope does not necessarily cause a conflict. For example, a using declaration inside main can hide a global function with the same name:

#include <iostream>

namespace A
{
    void print()
    {
        std::cout << "From A\n";
    }
}

void print()
{
    std::cout << "From global\n";
}

int main()
{
    using A::print;

    print();
    ::print();
    return 0;
}

Inside main, the using declaration for A::print makes A::print available through the unqualified name print. Calling print() therefore calls A::print. The global function still exists and can be reached explicitly by writing ::print().

A using declaration is a very sharp instrument. It imports exactly one name, doesn't touch any other names in the namespace, and is limited to the current scope. That's the best of both worlds-short names and no surprises

0 comments

No comments yet. Be the first.

Add a comment

About CppLearn

CppLearn is an interactive, free reference for modern C++. In each lesson, you'll find out how the language works, rather than just lines of code that you can copy and paste. We cover concepts starting from beginner lessons on fundamentals and proceed to templates, move semantics, smart pointers, and areas that usually trap or scare C++ learners.