无法在函数内声明运算符.Clang bug或spec?

Jon*_*eld 19 c++ infix-notation clang language-lawyer name-lookup

C的一个怪异角落案例是函数可以在其他函数中声明,例如

void foo(void)
{
  void bar(void); // Behaves as if this was written above void foo(void)
  bar();
}
Run Code Online (Sandbox Code Playgroud)

这已经贯彻到C++,至少对于大多数功能而言.如果有问题的函数恰好被称为operator ==,Clang似乎不会识别该模式.

struct foo
{
  int value;
};

struct bar
{
  foo value;
};

bool wot(const bar &x, const bar &y)
{
  bool eq(const foo &, const foo &);         // Declare function eq
  bool operator==(const foo &, const foo &); // Declare function operator==
  bool func = eq(x.value, y.value);          // This line compiles fine
  bool call = operator==(x.value, y.value);  // Also OK - thanks user657267!
  bool op = x.value == y.value;              // This one doesn't
  return func && call && op;
}

bool test()
{
  bar a;
  bar b;
  return wot(a,b);
}
Run Code Online (Sandbox Code Playgroud)

GCC和ICC编译此罚款.检查对象中的名称修改是否表示已使用正确的类型声明了运算符==.Clang(我尝试了3.8)错误:

error: invalid operands to binary expression
      ('const foo' and 'const foo')
      bool op = x.value == y.value;
                ~~~~~~~ ^  ~~~~~~~
Run Code Online (Sandbox Code Playgroud)

除非将声明移到函数的正上方,否则Clang也很高兴:

bool operator==(const foo &, const foo &);
bool wot(const bar &x, const bar &y)
{
  return x.value == y.value; // fine
}
Run Code Online (Sandbox Code Playgroud)

我无法使用此解决方法作为引发此问题的"真实世界"案例涉及模板层,这意味着我只知道函数声明中的类型名称"foo".

我相信这是Clang中的一个错误 - 是否有对operatorX free函数的特殊处理,禁止在函数内声明它们?

Col*_*mbo 7

对于重载运算符,请参见[over.match.oper] /(3.2):

[...]对于具有@cv非限定版本类型的左操作数的二元运算符和cv非限定版本类型的T1右操作数T2,[...] 非成员候选 [...]构造如下:

非成员候选集是根据非operator@限定函数调用(3.4.2)中的名称查找的通常规则在表达式的上下文中进行非限定查找的结果,除了忽略所有成员函数.但是,如果没有操作数具有类类型,[...]

也就是说,我们具有与普通调用中完全相同的名称查找规则,因为x.value它是类type(foo).这是一个Clang错误,它发生在所有二元运算符中.归档为#27027.