0

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};
}
11
  • You need some way to distinguish between the two functions. Right now they are exactly the same (their signature is exactly the same). How would the compiler, or even you, decide which one to use in which situation? Commented Feb 26, 2022 at 12:42
  • And for possible solutions, perhaps user-defined literals isn't the correct solution here for you "specific" way, perhaps you should consider a factory function instead? Especially if it's the exception to the "normal" way of creating ID objects. Commented Feb 26, 2022 at 12:43
  • I guess you can put the first _ID in a nested namespace, too. Then in each function you could import the right namespace and no collisions should occur. Commented Feb 26, 2022 at 12:45
  • 1
    I'll just use 1'000'000 instead of using _ID operator and there won't be any need to avoid any ambiguity. Commented Feb 26, 2022 at 12:58
  • 1
    If you want to use namespaces to differentiate between two otherwise equal functions (from the compilers perspective), then you can't be using using namespace ... to pull both functions into the same namespace. Either don't do using namespace literals; in the global namespace (use it at a narrower scope, like inside a function), or talk to your professor (or whoever gave you the assignment) if your requirements analysis, design and implementation are correct. Commented Feb 26, 2022 at 12:58

2 Answers 2

3

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};
}
Sign up to request clarification or add additional context in comments.

Comments

-1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.