I do not understand why neither the lambda nor the function are recognized as an std::invocable
compliant types in the following code:
#include <concepts>
#include <iostream>
void f( std::invocable auto callback)
{
callback(47);
}
void function_callback(int i)
{
std::cout << i << std::endl;
}
auto lambda_callback = [](int i )
{
std::cout << i << std::endl;
};
int main(int)
{
f(&function_callback);
f(lambda_callback);
}
I am using GCC trunk with -std=c++2a
flag enabled.
If you look at the definition of invocable
(or in the standard):
template< class F, class... Args >
concept invocable =
requires(F&& f, Args&&... args) {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
/* not required to be equality preserving */
};
What this means:
void f( std::invocable auto callback)
And it might be clearer if we write it long-form:
template <typename F>
requires std::invocable<F>
void f(F callback);
Is that F
is invocable with no arguments - that it's a nullary function (Args...
is an empty pack here). Neither your function nor your lambda are nullary functions - they're both unary, so the constraint correctly rejects those.
What you probably want is:
void f( std::invocable<int> auto callback)
which checks if callback
is invocable with a single argument of type int
.