Compiling the below program with g++-7 on gcc.godbolt.org and other self builts, and also older releases of g++: namespace A { class Foo {}; } namespace B { class Foo{}; } using namespace A; using namespace B; template <typename T> using t = T; using type = t<Foo>; //Foo* p = nullptr; gives the unhelpful error message maggot:/tmp>g++ -std=c++14 c.cpp c.cpp:13:19: error: template argument 1 is invalid using type = t<Foo>; Removing the comment for the Foo*, gives a considerably more helpful message: maggot:/tmp>g++ -std=c++14 c.cpp c.cpp:13:19: error: template argument 1 is invalid using type = t<Foo>; ^ c.cpp:15:1: error: reference to 'Foo' is ambiguous Foo* p = nullptr; ^ c.cpp:6:11: note: candidates are: class B::Foo class Foo{}; ^ c.cpp:3:11: note: class A::Foo class Foo {}; ^
More info: adding an alias for a function signature involving the ambiguous Foo in the above program gives a directly misleading error message: using type = void(Foo); c.cpp:12:18: error: expected ';' before '(' token using type = void(Foo); ^
Confirmed.
Here are a few more cases, reduced from a larger example that took me a very long time to understand. I'm adding as comments the compile error emitted for each invalid use: namespace N { template <typename T, typename U, typename V> struct Something { }; template <typename> concept C = true; template <typename> struct X { }; } using namespace N; template <typename T> struct Something { }; // parse error in template argument list static_assert(C<Something<int>>); // template argument 1 is invalid X<Something<int>> x; // reference to Something is ambiguous using T = Something<int>; In the last case, the compiler error is super clear and it is obvious what the error is. In the other two, not so much.
For Barry's example, Clang gives the exact same error in all three cases, which is much more useful: 79070.C:11:17: error: reference to 'Something' is ambiguous static_assert(C<Something<int>>); ^ 79070.C:8:30: note: candidate found by name lookup is 'Something' template <typename T> struct Something { }; ^ 79070.C:2:58: note: candidate found by name lookup is 'N::Something' template <typename T, typename U, typename V> struct Something { }; ^ 79070.C:14:3: error: reference to 'Something' is ambiguous X<Something<int>> x; ^ 79070.C:8:30: note: candidate found by name lookup is 'Something' template <typename T> struct Something { }; ^ 79070.C:2:58: note: candidate found by name lookup is 'N::Something' template <typename T, typename U, typename V> struct Something { }; ^ 79070.C:17:11: error: reference to 'Something' is ambiguous using T = Something<int>; ^ 79070.C:8:30: note: candidate found by name lookup is 'Something' template <typename T> struct Something { }; ^ 79070.C:2:58: note: candidate found by name lookup is 'N::Something' template <typename T, typename U, typename V> struct Something { }; ^ 3 errors generated.
*** Bug 97922 has been marked as a duplicate of this bug. ***