-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Description
Consider the easy mistake of forgetting to put public:
at the top of a class
:
class AlmostPred {
void operator()(int) const;
};
void f(std::predicate<int> auto p) {}
When you try to invoke f
you get a very confusing error that stops with: because 'is_invocable_v<AlmostPred, int>' evaluated to false
. If you don't already know the problem, it can be very frustrating to see that error because the operator()
with identical arguments is RIGHT THERE 😡. At least I was recently frustrated by debugging this. Compare that to the gcc trunk output which tells you exactly what is wrong and letting you click to go right to the place to fix it.
• 'AlmostPred' is not invocable by 'int', because
• error: 'void AlmostPred::operator()(int) const' is private within this context
• declared private here
<source>:6:10:
6 | void operator()(int) const;
| ^~~~~~~~
Clang does a bit better when you use requires
expressions directly in the function declaration rather than concepts (even though the general advice is to never do that and to always use named concepts instead). With void g(auto p) requires(requires(int i) {p(i);}){}
the error ends with because 'p(i)' would be invalid: 'operator()' is a private member of 'AlmostPred'
. This could be improved further by including a reference to the declaration of the private member and possibly even a fixit to add public:
to the top of the class (probably only if there are no protection markers in the class and it is just using the default).
Either way, the message about the function being private should be shown when attempting to use a concept. Really any concept failure should include the root cause of the failure, even if it skips a few steps between the named concept and the root cause by default for brevity.
clang trunk godbolt with both f
and g
clang trunk with libc++ (no better)
gcc trunk godbolt