Search code examples
c++gcccompiler-bug

GCC confuses `set` member function with `std::set`


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?


Solution

  • 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.