Search code examples
c++visual-c++language-lawyerfriendclang++

Function pointer to global operator compiles on VC++ while clang gives an error


I am trying to get the following code to compile on clang, but it fails with the following error:

error: no member named 'operator<' in the global namespace

I tried compiling the visual studio code with /Za to switch to standard conformance, but it still seems to accept it. Enlighten me please.

struct A
{
  int m_test;
  A(int test)
    : m_test(test)
  {

  }

  friend bool operator<(A left, A right);
};

int main()
{
  typedef bool(*TCompare)(A,A);
  TCompare compare = &::operator<;

  compare(9,7);
}

VC++ output: https://godbolt.org/g/LAz56n

Clang output: https://godbolt.org/g/zC2InO


Solution

  • Clang is correct. For your sample code, the name operator< introduced by friend declarations does become the member of the global namespace, but it's not visible to name lookup. It can only be found by ADL, but ADL only applies to function-call expressions, while &::operator< is not.

    Names introduced by friend declarations within a non-local class X become members of the innermost enclosing namespace of X, but they do not become visible to lookup (neither unqualified nor qualified) unless a matching declaration is provided at namespace scope, either before or after the class definition. Such name may be found through ADL which considers both namespaces and classes.

    To fix it you have to add a matching declaration at global namespace scope. e.g.

    struct A
    {
      int m_test;
      A(int test)
        : m_test(test)
      {
    
      }
    
      friend bool operator<(A left, A right);
    };
    
    // add a matching declaration at namespace scope
    bool operator<(A left, A right);
    
    int main()
    {
      typedef bool(*TCompare)(A,A);
      TCompare compare = &::operator<;
    
      compare(9,7);
    }
    
    bool operator<(A left, A right) { 
        ... 
    }