Почему С++ 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
.
Ответы
Ответ 1
Короткий ответ заключается в том, что для спецификации С++ 11 ваш A
будет CopyConstructible
использоваться с std::function
.
Долгий ответ - это требование существует, потому что std::function
стирает тип вашего функтора внутри конструктора. Для этого std::function
должен получить доступ к определенным членам вашего функтора с помощью виртуальных функций. К ним относятся оператор вызова, конструктор копирования и деструктор. И поскольку они доступны через виртуальный вызов, они "используются" независимо от того, используете ли вы фактически std::function
конструктор копирования, деструктор или оператор вызова.
Ответ 2
Это ошибка в Visual Studio. Он пытается выполнить эллипс копии (когда на самом деле он должен пытаться совершить переключение), для чего требуется доступный конструктор копирования. Лучшее решение - просто объявить оператор-конструктор/присваивание копии и никогда не определять их. Класс будет по-прежнему не скопирован, но код будет компилироваться, потому что VS никогда не попытается на самом деле вызвать конструктор копирования.