C ++ `std :: move` пользовательский тип в лямбда-захват - PullRequest
0 голосов
/ 03 мая 2020

У меня есть класс, в котором я удалил оператор назначения копирования и конструктор копирования, оставив только оператор назначения перемещения и конструктор перемещения. Например:

struct Number {
  public:
  int *pNum;

  Number &operator=(const Number &rhs) = delete;
  Number(const Number &rhs) = delete;

  Number &operator=(Number &&rhs) {
    if (&rhs == this) {
      return *this;
    }

    pNum = rhs.pNum;
    rhs.pNum = nullptr;
    return *this;
  }

  Number() = default;

  Number(Number &&rhs) {
    *this = std::move(rhs);
  }

  ~Number() {
    delete pNum;
  }
};

Теперь я хочу использовать std::move для захвата этого класса в лямбду. Например:

int main() {
  std::function<int(int)> add;


  int a = 3;

  {

    Number n{};
    n.pNum = new int;
    *n.pNum = 5;

    add = [&, capA{std::move(n)}](int) mutable -> int {
      int b = *capA.pNum; // 5
      return a + b; // 8
    };
  }

  std::cout << add(3);
}

Однако, похоже, что n будет const, так что c ++ попытается использовать конструктор удаленной копии. Как бы я это исправить? (REPL: https://repl.it/@25GrantY / WeirdLambda )

Ответы [ 2 ]

7 голосов
/ 03 мая 2020

Проблема не в лямбде. Например, это работает:

auto l = [&, capA{std::move(n)}](int) mutable -> int {
      int b = *capA.pNum; // 5
      return a + b; // 8
    };

Проблема в std::function и этой лямбде. Поскольку вы захватываете не копируемый объект, то лямбда не копируется. std::function требует, чтобы его сохраненный объект был копируемым, поэтому он не работает.

Вы можете прочитать больше здесь: Версия std :: function * 1010 только для перемещения

3 голосов
/ 03 мая 2020

проблема здесь исходит от std :: function. Этот класс должен соответствовать требованиям CopyConstructible и CopyAssignable, согласно документации. https://en.cppreference.com/w/cpp/utility/functional/function

std :: function удовлетворяет требованиям CopyConstructible и CopyAssignable.

При попытке инициализации std :: function с помощью Лямбда, которая захватывает тип «только для перемещения» по значению, такое назначение (если оно выполнено успешно) нарушит оба вышеуказанных требования.

Вот почему компиляция завершается с ошибкой.

Как это исправить ?

Либо не используйте std :: function, либо сделайте свою лямбда-копию копируемой.

Вы можете использовать std :: shared_ptr в качестве копируемой оболочки для типа только для перемещения.

auto shared_number = std::make_shared<Number>{};

Теперь вы можете передать shared_number в lambda и присвоить std :: function.

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