Consider the following code:
int main() {
auto const fn = [] mutable {};
fn(); // ok, why?
}
As per the latest C++ standard draft [expr.prim.lambda.closure] 7.5.6.2/6 (emphasis mine):
The function call operator or operator template is a static member function or static member function template (11.4.9.2) if the lambda-expression’s parameter-declaration-clause is followed by static. Otherwise, it is a non-static member function or member function template (11.4.3) that is declared const (11.4.3) if and only if the lambda-expression’s parameter-declaration-clause is not followed by mutable and the lambda declarator does not contain an explicit object parameter.
Since the lambda is marked as mutable
, then:
operator()
should be marked as non-const.auto const fn
means fn
is a const object, so fn
cannot call the non-const operator()
.However, both gcc & clang accept the code above, see https://godbolt.org/z/5Gohefz7o
Why can a const object call a non-const member function?
CppInsights might help to understand Demo:
class __lambda_2_21
{
public:
inline /*constexpr */ void operator()() {}
using retType_2_21 = void (*)();
inline constexpr operator retType_2_21 () const noexcept
{
return __invoke;
}
private:
static inline /*constexpr */ void __invoke()
{
__lambda_2_21{}.operator()();
}
};
const __lambda_2_21 fn = __lambda_2_21{};
fn.operator __lambda_2_21::retType_2_21()();
You don't call the non-const operator()
, but as the lambda is capture-less,
you call the function pointer (provided with conversion operator).