decltype(a)
is int
. This corresponds to invoking f
with an int
prvalue — something like f(7)
. That one indeed doesn’t compile, because a non-const
lvalue reference cannot bind to a prvalue.
What you’re doing instead in main
is calling f
with an lvalue, a
, to which the reference can bind just fine.
To get the correct result from std::is_invocable
, use the expression form of decltype
by adding parentheses:
std::is_invocable_v<decltype(foo), decltype((a))>
// ^ ^