Jan Nils Ferner Jan Nils Ferner - 16 days ago 6
C++ Question

Who is correct here, GCC or MSVC?

Suppose we have this structure:

namespace some_namespace::types {
using foo_t = int;
}

namespace some_namespace::classes {
class bar {
public:
auto do_stuff() -> types::foo_t;
};
}

using namespace some_namespace::classes;

auto bar::do_stuff() -> types::foo_t {
return 1;
}


This code compiles happily in GCC6.

On the other hand, VS15 with the
/std:c++latest
switch enabled doesn't recognize the return type of
do_stuff
. It returns C2653.

Now, what I find highly suspicious is that this gets fixed by changing the second half to this:

using namespace some_namespace;

auto classes::bar::do_stuff() -> types::foo_t {
return 1;
}


which in my eyes should be equal. Am I mistaken in thinking that this is a MSVC bug? What does the standard say about this?

Answer

This has nothing to do with the C++17 feature, which didn't touch using-directives, nor indeed with using-directives at all. MSVC produces the same error from

namespace some_namespace{
    namespace types {
        using foo_t = int;
    }
    namespace classes {
        class bar {
        public:
            auto do_stuff() -> types::foo_t;
        };
    }
}

using some_namespace::classes::bar;

auto bar::do_stuff() -> types::foo_t {
    return 1;
}

[basic.lookup.unqual]/8:

For the members of a class X, a name used [...] in the definition of a class member outside of the definition of X, following the member's declarator-id, shall be declared in one of the following ways:

  • before its use in the block in which it is used or in an enclosing block ([stmt.block]), or

  • shall be a member of class X or be a member of a base class of X ([class.member.lookup]), or

  • [...two bullet points about nested and local classes omitted...]

  • if X is a member of namespace N [...], before the use of the name, in namespace N or in one of N's enclosing namespaces.

Name lookup for types should first look inside bar, then inside classes, then inside some_namespace. That last one should find the namespace types.

Comments