#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'
}
参见 online demo
为什么 C++ lambda 重载的行为不如预期?
最佳答案
- 您的问题几乎与 Hard error when using std::invoke_result_t with a generic lambda 重复.与另一个问题一样,如果您更改 lambda 以使其具有明确的
-> void
返回类型,您的代码将按您期望的方式工作,从而避免返回类型推导。 - 您的问题与另一个问题的区别在于,在您的问题中,您使用的是
std::invocable_v
而不是std::invoke_result_t
。但是,这种情况下的代码仍然是错误的,因为即使您没有要求,返回类型推导仍然会被触发。 - 该标准要求
is_invocable
来确定 INVOKE 表达式是否“在被视为未计算的操作数时格式正确”。 libstdc++ 和 libc++ 都使用decltype
为此目的创建一个未计算的操作数,因此,很明显,必须进行返回类型推导。但在我看来 there is no way to avoid triggering return type deduction ,因此没有可能允许您的代码编译的标准库实现(这不是 GCC/Clang 中的错误)。
关于c++ - 为什么 C++ lambda 重载的行为不如预期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68778339/