Неконстантный лямбда-захват в константном методе - PullRequest
1 голос
/ 04 февраля 2020
#include <iostream>
#include <functional>

class Blub {
public:
    int i = 0;
    std::function<void()> create() const {
        return [this]() {
            this->i = 100;
        };
    }
};

int main() {
    Blub blub = Blub();
    blub.create()();
    std::cout << blub.i << std::endl;
    return 0;
}

Я знаю, что this записывается как const внутри лямбды, потому что метод помечен как const. Есть ли еще способ, кроме удаления константности метода, архивировать, что я могу изменить переменные-члены внутри лямбда-функции?

Добавление ключевого слова mutable не работает.

Ответы [ 2 ]

3 голосов
/ 04 февраля 2020

Вы можете объявить переменную-член i как mutable, чтобы она могла измениться, даже если объект объявлен как const:

class Blub {
public:
    mutable int i = 0;
//  ^^^^^^^
    std::function<void()> create() const {
        return [this]() {
            this->i = 100;
        };
    }
};

Live здесь .

2 голосов
/ 04 февраля 2020

Вы можете сделать следующее обходной путь :

class Blub {
public:
    int i = 0;
    std::function<void()> create() const {
        return [my_this=const_cast<Blub*>(this)]() {
            my_this->i = 100;
        };
    }
};

, но вводить в заблуждение изменение элемента данных в функции, которая фактически помечена как const, поэтому я бы не стал предложите разработать свой класс таким образом.

Проверьте это live .

NB Стоит отметить, что const_cast безопасен для используйте только если он используется для приведения переменной, которая изначально была не const. Если переменная изначально const, использование const_cast может привести к неопределенному поведению. Итак, в следующем коде (который предоставил OP):

int main() {
    Blub blub = Blub();
    blub.create()();
    std::cout << blub.i << std::endl;
    return 0;
}

безопасно использовать const_cast, потому что объект изначально сделан не-1023 *. Однако, если мы сделаем это const, как в следующем коде:

int main() {
    const Blub blub = Blub();
    blub.create()();
    std::cout << blub.i << std::endl;
    return 0;
}

, это приведет к неопределенному поведению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...