The following C++ code gives an error with GCC (e.g. 13.1, see godbolt.org) where the compiler seems to confuse the set
member function template with std::set
:
#include <set>
using namespace std;
template <typename T> struct C {
template <int S> void set(T const &) { }
};
template <typename T> struct D : C<T> {
void f(T const & v) { this->template set<0>(v); }
};
It has obviously something to do with the using namespace std;
line but I don't understand how the compiler can try to lookup set
in the global or std
namespace when it is explicitly qualified by this->
. Can anyone enlighten me?
There is a GCC bug report about this here.
According to the comments there is a relevant C++ standard defect report regarding the behavior, but I couldn't find it.
For a bit of context:
When you have a class member access expression like X->Y
(assuming no operator->
overload), lookup for Y
is done first in the context of the class type of X
.
But if that doesn't succeed, then lookup for Y
is also done in the scope of the expression. This would e.g. find std::set
if Y
is set
and you have a using namespace std;
in scope (template
doesn't affect the lookup). Because your base class C<T>
is dependent its member set
won't be found in the first lookup phase from the template definition context.
This lookup rule allows you to write e.g. this->set<int>::size()
if the current class is derived from set<int>
.
The question now is how this is supposed to interact with the current class having a dependent base that could cause lookup for set
to find its member instead in the instantiation context.
I haven't looked up what the current and previous standards say about this exactly.