#include <type_traits>
template<typename T, typename... Args_>
concept IsCallable = std::is_invocable_v<T, Args_...>;
struct A
{
int n = 0;
void f(IsCallable<int&> auto const fn)
{
fn(n);
}
void f(IsCallable<int const&> auto const fn) const
{
fn(n);
}
};
struct Lambda
{
void operator()(auto& n) const
{
n = 1;
}
};
int main()
{
auto a = A{};
a.f(Lambda{}); // ok
a.f([](auto& n) { n = 1; }); // error: assignment of read-only reference 'n'
}
See online demo
Why does C++ lambda overloading not behave as expected?
-> void return type, thus avoiding return type deduction.std::invocable_v rather than std::invoke_result_t. However, the code in this case is still ill-formed because return type deduction is still triggered even though you're not asking for it.is_invocable to determine whether or not the INVOKE expression would be "well-formed when treated as an unevaluated operand". libstdc++ and libc++ both use decltype to create an unevaluated operand for this purpose, so, obviously, return type deduction has to be done. But it seems to me that there is no way to avoid triggering return type deduction, therefore there is no possible standard library implementation that would allow your code to compile (it is not a bug in GCC/Clang).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