2012-08-01 8 views
15
//------------------------------------------------------------------------------ 
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': no ​​se puede miembro privado de acceso declarado en la clase 'A'¿Por qué C++ 11 no puede mover un functor no copiable a una función std ::?

Parece que cuando capturo algo por referencia o const PUEDO lambda no copiable. Sin embargo, cuando lo hago, realmente funciona para darle un std::function.

+1

Como [solución temporal] (https://gist.github.com/vmilea/5815777), puede poner un adaptador que se puede copiar entre std :: function y su functor. El adaptador tiene un constructor de copia ficticio (mover en la copia) y tira si se copia. –

Respuesta

19

La respuesta corta es que la especificación C++ 11 requiere que su A sea CopyConstructible para ser utilizado con std::function.

La respuesta larga es que este requisito existe porque std::function borra el tipo de su functor dentro del constructor. Para hacer esto, std::function debe acceder a ciertos miembros de su functor a través de funciones virtuales. Estos incluyen el operador de llamada, el constructor de copia y el destructor. Y dado que se accede a ellos a través de una llamada virtual, se "usan" independientemente de si realmente usa std::function como constructor de copias, destructor o operador de llamadas.

+0

Corrígeme si estoy equivocado (y probablemente lo esté) pero, para usar funciones virtuales, necesitas un vtable y, por lo tanto, una clase base. ¿Cuál es la clase base en este caso? – akappa

+5

Consulte http://stackoverflow.com/questions/6324694/type-erasure-in-c-how-boostshared-ptr-and-boostfunction-work para obtener una descripción de cómo funciona el borrado de tipos. La clase base es un detalle de implementación de std :: function. La clase derivada también es un detalle de implementación, pero también está modelada en el funtor suministrado. –

+0

muy interesante, gracias. – akappa

-1

Es un error en Visual Studio. Intenta eludir una copia (cuando en realidad debería tratar de eludir un movimiento), lo que requiere un constructor de copia accesible. La mejor solución es simplemente declarar el operador de asignación/constructor de copia y nunca definirlos. La clase seguirá siendo no copiable pero el código se compilará, porque VS nunca intentará llamar al constructor de copia.

+3

Aparentemente, intenta llamar al copiador si hago lo que sugiere, porque obtengo una respuesta externa no resuelta. – David

+0

@Dave: Sí, es por eso que es un * error *. El estándar dice que debería permitirse, pero VS no lo hace bien. –

+0

@NicolBolas Está bien, pero su sugerencia provisional no funcionó. No puedo decir eso? (Agradezco la respuesta a través de DeadMG, gracias) – David

Cuestiones relacionadas