Member-only story

C++ — Why can’t a const mutable lambda with an auto& parameter be invoked?

Flutter Developer
2 min readDec 15, 2021

--

Example:

#include <type_traits>

int main()
{
auto f1 = [](auto&) mutable {};
static_assert(std::is_invocable_v<decltype(f1), int&>); // ok

auto const f2 = [](auto&) {};
static_assert(std::is_invocable_v<decltype(f2), int&>); // ok

auto const f3 = [](auto&) mutable {};
static_assert(std::is_invocable_v<decltype(f3), int&>); // failed
}

There are two interesting things here.

First, a lambda’s call operator (template) is const by default. If you provide mutable, then it is not const. The effect of mutable on a lambda is solely the opposite of the effect of trailing const in normal member functions (it does not affect lambda capture, etc.)

So if you look at this:

auto const f3 = [](auto&) mutable {};
static_assert(std::is_invocable_v<decltype(f3), int&>); // failed

This is a const object, whose call operator template (because it's a generic lambda) is non-const. So you can't invoke it, for the same reason you can't invoke a non-const member function on a const object in any other context. See this other answer.

Second, it has been pointed out that, nevertheless, this works:

auto const f4 = [](int&) mutable {}; // changed auto& to int&
static_assert(std::is_invocable_v<decltype(f4), int&>); // now ok

--

--

Flutter Developer
Flutter Developer

Written by Flutter Developer

Flutter and Native Android developer

No responses yet