Подтвердить что ты не робот

Почему С++ 11 не может перемещать некомпьютерный функтор в std:: function?

//------------------------------------------------------------------------------
struct A
{
    A(){}
    A(A&&){}
    A& operator=(A&&){return *this;}
    void operator()(){}

private:
    A(const A&);
    A& operator=(const A&);

    int x;
};

//------------------------------------------------------------------------------
int main()
{
    A a;
    std::function<void()> func(std::move(a));
}

'A:: A': не может получить доступ к закрытому члену, объявленному в классе 'A'

Кажется, что когда я фиксирую что-то по ссылке или const, я могу сделать не скопируемую лямбду. Однако, когда я это делаю, он действительно работает, чтобы дать ему std::function.

4b9b3361

Ответ 1

Короткий ответ заключается в том, что для спецификации С++ 11 ваш A будет CopyConstructible использоваться с std::function.

Долгий ответ - это требование существует, потому что std::function стирает тип вашего функтора внутри конструктора. Для этого std::function должен получить доступ к определенным членам вашего функтора с помощью виртуальных функций. К ним относятся оператор вызова, конструктор копирования и деструктор. И поскольку они доступны через виртуальный вызов, они "используются" независимо от того, используете ли вы фактически std::function конструктор копирования, деструктор или оператор вызова.

Ответ 2

Это ошибка в Visual Studio. Он пытается выполнить эллипс копии (когда на самом деле он должен пытаться совершить переключение), для чего требуется доступный конструктор копирования. Лучшее решение - просто объявить оператор-конструктор/присваивание копии и никогда не определять их. Класс будет по-прежнему не скопирован, но код будет компилироваться, потому что VS никогда не попытается на самом деле вызвать конструктор копирования.