C语言中比较奇特的一种情况是函数可以在其他函数内部声明,例如:
void foo(void)
{
void bar(void); // Behaves as if this was written above void foo(void)
bar();
}
这种情况也出现在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);
}
GCC和ICC编译可以正常通过。在对象中检查名称混淆表明operator==已经用正确的类型声明。Clang(我尝试了3.8版本)报错:
error: invalid operands to binary expression
('const foo' and 'const foo')
bool op = x.value == y.value;
~~~~~~~ ^ ~~~~~~~
除非将声明移动到函数的正上方,否则Clang会报错。如果将声明移动到函数正上方,Clang就不会报错了。
bool operator==(const foo &, const foo &);
bool wot(const bar &x, const bar &y)
{
return x.value == y.value; // fine
}
我无法使用这个解决方法,因为引发这个问题的“真实世界”情况涉及多层模板,这意味着我只知道函数声明中的类型名称“foo”。
我认为这是Clang中的一个bug - 是否有operatorX自由函数的特殊处理方式,禁止在函数内部声明它们?
bool op = operator==(x.value, y.value);
看起来工作正常,但出于某种原因,Clang 的操作符查找未能找到块作用域声明。 - user657267a@b
会在任何其他事情发生之前引起一个非成员候选函数operator@(a,b)
,所以第二个形式有效而第一个不是则强烈表明存在一个错误。 - M.M