这里有两件有趣的事情。
首先,lambda 的调用运算符(模板)默认为const。如果您提供mutable,则它不是const。 mutable 对 lambda 的影响完全与普通成员函数中尾随 const 的影响相反(它不影响 lambda 捕获等)
所以如果你看这个:
auto const f3 = [](auto&) mutable {};
static_assert(std::is_invocable_v<decltype(f3), int&>); // failed
这是一个const 对象,其调用运算符模板(因为它是一个通用 lambda)不是const。所以你不能调用它,出于同样的原因,你不能在任何其他上下文中调用const 对象上的非const 成员函数。见this other answer。
第二,有人指出,尽管如此,这是可行的:
auto const f4 = [](int&) mutable {}; // changed auto& to int&
static_assert(std::is_invocable_v<decltype(f4), int&>); // now ok
这不是编译器错误。 也没有 不是说我刚才说的是错的。 f4 still 有一个 non-const 调用运算符。您不能调用它,因为 f4 是一个 const 对象。
但是。
lambda 还有另一个有趣的方面没有捕获:它们具有到函数指针类型的转换函数。也就是说,我们通常认为 lambda f4 看起来像这样:
struct __unique_f4 {
auto operator()(int&) /* not const */ { }
};
而且,如果这就是整个故事,const __unique_f4 确实不能用int& 调用。但它实际上是这样的:
struct __unique_f4 {
auto operator()(int&) /* not const */ { }
// conversion function to the appropriate function
// pointer type
operator void(*)(int&)() const { /* ... */ }
};
我们有一条规则,当你调用一个对象时,比如f(x),你不仅考虑f的调用操作符——那些名为operator()的成员——而且你还考虑任何@ 987654344@'s surrogate call functions -- 是否有任何函数指针可以将f 转换为,然后调用。
在这种情况下,你可以!您可以将f4 转换为void(*)(int&),并且可以使用int& 调用该函数指针。
但这仍然意味着f4 的调用运算符不是 const,因为您声明它是可变的。它并没有说明你是否可以让mutable lambdas 接受引用参数。