指向全局运算符的函数指针在VC++上编译,而clang则给出错误

cag*_*man 1 c++ friend visual-c++ language-lawyer clang++

我试图在clang上编译以下代码,但它失败并出现以下错误:

error: no member named 'operator<' in the global namespace
Run Code Online (Sandbox Code Playgroud)

我尝试使用/ Za编译visual studio代码以切换到标准一致性,但它似乎仍然接受它.请赐教.

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);
}
Run Code Online (Sandbox Code Playgroud)

VC++输出:https://godbolt.org/g/LAz56n

Clang输出:https://godbolt.org/g/zC2InO

n. *_* m. 5

这是一个VC++错误.代码无效.

友元声明不会将声明的名称引入全局命名空间.你仍然需要在课堂外声明它.


son*_*yao 5

铿锵是对的.对于示例代码,友元声明operator<引入的名称确实成为全局命名空间的成员,但名称查找不可见.它只能由ADL找到,但ADL仅适用于函数调用表达式,而不是.&::operator<

非本地类中的友元声明引入的名称X 成为最内层封闭命名空间的成员X,但它们不会对查找可见(既不合格也不合格),除非在命名空间范围内提供匹配声明,无论是在类之前还是之后定义.可以通过ADL找到这样的名称,ADL同时考虑名称空间和类.

要修复它,您必须在全局命名空间范围内添加匹配的声明.例如

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) { 
    ... 
}
Run Code Online (Sandbox Code Playgroud)