c++ - ¿Por qué el operador de llamada de la lambda está implícitamente implícito?




c++11 const (2)

Creo que es simplemente evitar la confusión cuando una variable dentro de un lambda no se refiere a lo que originalmente se capturó. Léxicamente, tal variable es como si estuviera en el alcance de su "original". La copia es principalmente para permitir extender la vida útil del objeto. Cuando una captura no es por copia, se refiere al original y las modificaciones se aplican al original, y no hay confusión debido a dos objetos diferentes (uno de los cuales se introduce implícitamente), y está permitido por el operador de llamada a la función const de lambda.

Tengo una pequeña "expresión lambda" en la siguiente función:

int main()
{
    int x = 10;
    auto lambda = [=] () { return x + 3; };
}

A continuación se muestra la "clase de cierre anónimo" generada para la expresión lambda anterior.

int main()
{
    int x = 10;

    class __lambda_3_19
    {
        public: inline /*constexpr */ int operator()() const
        {
            return x + 3;
        }

        private:
            int x;

        public: __lambda_3_19(int _x) : x{_x}
          {}

    };

    __lambda_3_19 lambda = __lambda_3_19{x};
}

El "operador ()" del cierre generado por el compilador es implícitamente constante. ¿Por qué el comité estándar lo hizo const por defecto?


De cppreference

A menos que la palabra clave mutable se haya utilizado en la expresión lambda, el operador de llamada de función está cualificado constantemente y los objetos que fueron capturados por copia no son modificables desde el interior de este operator()

En su caso, no hay nada que, capturado por copia, sea modificable.

Supongo que si escribes algo como

int x = 10;

auto lambda = [=] () mutable { x += 3; return x; };

la const debería desaparecer

- EDITAR -

La OP precisa

Ya sabía que agregar mutable resolverá el problema. La pregunta es que quiero entender la razón detrás de hacer que la lambda sea inmutable por defecto.

No soy un abogado de idiomas, pero esto me parece obvio: si haces operator() no const , no puedes hacer algo como

template <typename F>
void foo (F const & f)
 { f(); }

// ...

foo([]{ std::cout << "lambda!" << std::endl; });

Quiero decir ... si el operator() no es const , no puede usar las lambdas que pasan como referencia const .

Y cuando no es estrictamente necesario, debe ser una limitación inaceptable.





function-call-operator