cageman cageman - 4 years ago 56
C++ Question

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

Answer Source

Clang is correct. For your sample code, the name operator< intruduced by friend declarations does become the member of 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) { 
    ... 
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download