2011-12-19 27 views
12

El código siguiente se compila con sonido metálico 3.0/libC++:std :: make_shared, std :: unique_ptr y mover constructores

#include <memory> 

class Foo 
{ 
public: 
    Foo() 
     : mem_(new int(10)) 
    { 
    } 
    std::unique_ptr<int> mem_; 
}; 

int main() 
{ 
    auto foo = std::make_shared<Foo>(); 
    return 0; 
} 

Pero éste no (std::string añadido el parámetro):

#include <memory> 
#include <string> 

class Foo 
{ 
public: 
    Foo(const std::string& s) 
     : mem_(new int(10)) 
    { 
    } 
    std::unique_ptr<int> mem_; 
}; 

int main() 
{ 
    auto foo = std::make_shared<Foo>("aaa"); 
    return 0; 
} 

Clang se queja del uso de un constructor eliminado. Para mí, esto no tiene sentido, ya que no se supone que std::make_shared copie la instancia de Foo, lo único que activaría la llamada al constructor de copia (eliminado) de std::unique_ptr.

Pero he aquí, tan pronto como defino un constructor de movimiento explícitamente, se compila.

#include <memory> 
#include <string> 

class Foo 
{ 
public: 
    Foo(const std::string& s) 
     : mem_(new int(10)) 
    { 
    } 
    Foo(Foo&& other) 
     : mem_(std::move(other.mem_)) 
    { 
    } 
    std::unique_ptr<int> mem_; 
}; 

int main() 
{ 
    auto foo = std::make_shared<Foo>("aaa"); 
    return 0; 
} 

Ahora, las preguntas:

  1. ¿Por qué se compilan en el primer ejemplo, pero no el segundo?
  2. ¿Puede std::make_shared copiar/mover el objeto mientras lo construye?
  3. ¿Por qué agregar un constructor de movimiento soluciona el problema? No recuerdo que la adición de un constructor no predeterminado deba suprimir un constructor de movimiento implícito.

EDIT: comprobado y todos los ejemplos parecen compilarse bien con gcc 4.5.1 (a través de ideone.com), sospecho que es el caso de un fallo de sonido metálico/libC++, pero las preguntas 2 y 3 siguen en pie, Además, me gustaría saber qué compilador es más "correcto".

+1

No creo que alguna vez hay un constructor de movimiento implícito proporcionado –

+0

@parapura rajkumar (1) eliminación de unique_ptr hace que desaparezca (incluso con no predeterminado ctor), (2) el constructor de movimiento implícito todavía se define según la última redacción: http: //mmocny.wordpress.com/2010/12/09/implicit-move-wont-go/ –

+0

@parapurarajkumar: de hecho, recuerdo haber leído discusiones donde los constructores de movimientos implícitos eran algo malo, y deberían eliminarse del estándar. Sin embargo, no sé el final de la historia. –

Respuesta

20

¿Por qué se compila en el primer ejemplo pero no en el segundo?

Esto es un error de libC++. Estoy trabajando en una solución ahora ...

Can std :: make_shared ¿copiar/mover el objeto mientras lo construyes?

No, no lo creo.

¿Por qué agregar un constructor de movimiento soluciona el problema? No recuerdo que al agregar un constructor no predeterminado debería suprimir un movimiento implícito constructor.

En la versión de clang que estás utilizando, los constructores de movimientos implícitos aún no están implementados.

actualización

fijo: http://llvm.org/bugs/show_bug.cgi?id=11616

+5

¡Guau! una hora vuelta! Entonces, si encontramos otros errores en clang/libC++, podemos publicarlos en Stackoverflow para avergonzarlo y arreglarlos rápidamente. –

+3

@deft_code: Creo que Howard es lo suficientemente honrado como para corregir errores sin sentirse avergonzado. ; -] – ildjarn

+3

@deft_code: Esa parece ser una técnica de efecto. ;-) –

Cuestiones relacionadas