Marcin K
Marcin K

Reputation: 871

typedef resolution across namespaces

I am currently confused with the way "using (namespace)" statements work in C++.

I have:

//somewhere in included headers
typedef unsigned int uint;

namespace mine {
    typedef unsigned int uint;
}
namespace other {
    using namespace mine;
    void foobar () {
        uint offender = i;
    }
}

Results in (paraphrased):
reference to 'uint' is ambiguous. candidates are
typedef unsigned int uint
and
typedef unsigned int mine::uint

Meanwhile, when I do

namespace other {
    using namespace mine;
    using mine::uint;

    void foobar () {
        uint offender = i;
    }
}

Everything works fine. It seems strange to me that "using identifier;" changes the visibility of other typedef definition (conceals the global one?). Can someone point me to what kind of rules in C++ govern resolution of typedefs across namespaces?

Upvotes: 10

Views: 21767

Answers (4)

CB Bailey
CB Bailey

Reputation: 791421

A name made visible by a using-directive appears in the nearest enclosing scope that contains [- directly or indirectly -] both the using-directive and the nominated namespace. (7.3.4 [namespace.udir])

This means that both uint declarations appear at the global namespace scope when looked up after the using-directive in other.

A using-declaration, like any other declaration, declares a name at the scope in which it appears. This is why, in the second example, using mine::uint; hides the uint introduced by using namespace mine; as the latter appears to come from the global scope.

Upvotes: 13

Mark Ransom
Mark Ransom

Reputation: 308111

I can't cite chapter and verse for you, but this makes sense to me. If the compiler can't find the symbol uint in the current namespace, it looks to other namespaces to see if it can find the symbol there. Since it finds it in two other namespaces, it's ambiguous.

When you said using mine::uint you imported that symbol into the current block, so it's found before the other namespaces need to be checked.

Upvotes: 1

Peon the Great
Peon the Great

Reputation: 1319

Your original code confuses the compiler, because the uint can be either

::uint

or

::mine::uint

therefore compiler throws that error message to you. In the "fix", the using mine::uint explicitly specified that ::mine::uint shall be preferred.

However, typedef conflict shall be avoided IMO. It makes the code so hard to maintain.

Upvotes: 5

Marcelo Cantos
Marcelo Cantos

Reputation: 185852

It doesn't conceal the global one. That's why you have the ambiguity.

Upvotes: 0

Related Questions