One of the weirder corner cases of C is that functions can be declared within other functions, e.g.
void foo(void)
{
void bar(void); // Behaves as if this was written above void foo(void)
bar();
}
This has carried through into C++, at least for most functions. Clang doesn't appear to recognise the pattern if the function in question happens to be called operator==.
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 and ICC compile this fine. Checking name mangling in the object suggests the operator== has been declared with the right types. Clang (I tried up to 3.8) errors:
error: invalid operands to binary expression
('const foo' and 'const foo')
bool op = x.value == y.value;
~~~~~~~ ^ ~~~~~~~
Unless the declaration is moved to directly above the function, in which case Clang is happy too:
bool operator==(const foo &, const foo &);
bool wot(const bar &x, const bar &y)
{
return x.value == y.value; // fine
}
I can't use this workaround as the "real world" case that provoked this question involves layers of templates, meaning I only know the type name "foo" within the function declaration.
I believe this is a bug in Clang - is there special handling of operatorX free functions which prohibits declaring them within a function?
For overloaded operators, see [over.match.oper]/(3.2):
[…] for a binary operator
@
with a left operand of a type whose cv-unqualified version isT1
and a right operand of a type whose cv-unqualified version isT2
, […] non-member candidates […] are constructed as follows:The set of non-member candidates is the result of the unqualified lookup of
operator@
in the context of the expression according to the usual rules for name lookup in unqualified function calls (3.4.2) except that all member functions are ignored. However, if no operand has a class type, […]
That is, we have the exact same name lookup rules as in ordinary calls, because x.value
is of class type (foo
). It's a Clang bug, and it occurs with all binary operators. Filed as #27027.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With