David Hovsepyan
David Hovsepyan

Reputation: 626

How to use nested namespace to avoid ambiguity?

I have the following operators defined in the corresponding namespaces:

namespace literals
{

constexpr ID operator"" _ID(const unsigned long long dyngateID)
{
    // ...
    // return a constructed id
}

namespace multiplied
{

constexpr ID operator"" _ID(const unsigned long long dyngateID)
{
    // ...
    // return an id constructed in a specific way
}

} // namespace multiplied
} // namespace literals

In a .cpp file I would like to use both functions, hence I've declared using namespace literals and when I am declaring using namespace multiplied in a concrete function I am getting ambiguous call to overloaded function compile error. How can I differentiate these functions?

Test.cpp

using namespace literals;

void f()
{
    // here I am using literals' _ID which is fine
    const Type id{1_ID};
}
void g()
{
    // here I want to use multiplied's _ID, but obviously I am failing to do so
    using namespace multiplied;
    const Type id{1_ID};
}

Upvotes: 0

Views: 280

Answers (2)

user17732522
user17732522

Reputation: 76628

The name lookup rules for using namespace are such that the declarations introduced by it appear to be located in the inner-most namespace scope enclosing both the current namespace scope and the target namespace scope.

Therefore it is no good to disambiguate based on the scoping of multiple reachable using namespace statements.

Instead you can import the declaration with a using declaration:

void g()
{
    using multiplied::operator""_ID;
    const Type id{1_ID};
}

This will behave as if the operator was declared in the scope, so that name lookup will stop there and won't look at the declaration imported by the outer using namespace.


Alternatively, you can call the user-defined literal operator directly with a qualified call:

void g()
{
    const Type id{multiplied::operator""_ID(1)};
}

As another possibility you can always limit the scope of the using namespace statements, so that only one of using namespace literals; or using namespace literals::multiplied; is reachable from any given scope using the operator, e.g.:

// no using namespace at this scope

void f()
{
    using namespace literals;
    const Type id{1_ID};
}
void g()
{
    using namespace literals::multiplied;
    const Type id{1_ID};
}

Upvotes: 3

The Coding Fox
The Coding Fox

Reputation: 1585

Consider the following code:

#include <iostream>

namespace one
{
    int func(int num1, int num2)
    {
        return num1 * num2;
    }

    namespace two
    {
        int func(int num1, int num2)
        {
            return num1 * num2;
        }
    }
}

int f()
{
    return one::two(1, 2) + 10;
}
int g()
{
    return one::two::func(3, 4) + 10;
}

int main()
{
    std::cout << f() << std::endl; 
    std::cout << g() << std::endl;
}

The above code will compile and run perfectly fine, and will work as expected, with f() using one::func() and g() using one::two::func(). If you have to write `using namespace one;' then you can do something like this:

using namespace one;

int f()
{
    return func(1, 2) + 10;
}
int g()
{
    return two::func(3, 4) + 10;
}

This will also result in the same output.

Upvotes: -1

Related Questions