2011-12-19 3 views
12

Il seguente codice compila con clangore 3.0/libC++:std :: make_shared, std :: unique_ptr e spostare costruttori

#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; 
} 

Ma questo non (std::string parametro aggiunta):

#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 lamenta l'utilizzo di un costruttore eliminato. Per me, questo non ha senso, dal momento che std::make_shared non dovrebbe copiare l'istanza Foo, l'unica cosa che farebbe scattare la chiamata al (cancellato) costruttore di copia di std::unique_ptr.

Ma ecco, non appena mi definisco un costruttore mossa in modo esplicito, si 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; 
} 

Ora, le domande:

  1. Perché si compilare nel primo esempio, ma non la seconda?
  2. Può std::make_shared copia/spostare l'oggetto, mentre la costruzione è?
  3. Perché l'aggiunta di un costruttore mossa risolvere il problema? Non ricordo che l'aggiunta di un costruttore non predefinito dovrebbe sopprimere un costruttore di mosse implicito.

EDIT: Controllato e tutti gli esempi sembrano per compilare bene con gcc 4.5.1 (via ideone.com), ho il sospetto che sia il caso di un bug clang/libC++, ma le domande 2 e 3 ancora in piedi, in più vorrei sapere quale compilatore è più "corretto".

+1

Io non credo che ci sia mai una mossa costruttore implicita fornita –

+0

@parapura Rajkumar (1) rimozione di unique_ptr fa andare via (anche con non predefinita ctor), (2) il costruttore di movimenti impliciti è ancora definito secondo l'ultimo testo: http: //mmocny.wordpress.com/2010/12/09/implicita-move-wont-go/ –

+0

@parapurarajkumar: discussioni in effetti, mi ricordo di aver letto in cui i costruttori si muovono impliciti erano una brutta cosa, e deve essere rimosso dallo standard. Tuttavia, non conosco la fine della storia. –

risposta

20

Perché compila nel primo esempio ma non nel secondo?

Questo è un errore di libC++. Sto lavorando a una correzione per ora ...

Può std :: make_shared copiare/spostare l'oggetto mentre lo costruisce?

No, non credo che possa.

Perché l'aggiunta di un costruttore di spostamenti risolve il problema? Non ricordo che l'aggiunta di costruttore non predefinito dovrebbe sopprimere un implicito mossa costruttore.

Nella versione di clang che si sta utilizzando, i costruttori di spostamento impliciti non sono ancora implementati.

Aggiornamento

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

+5

Wow! Un'ora si gira! Quindi se troviamo altri bug in clang/libC++ possiamo semplicemente postarli su Stackoverflow per farti vergognare a correggerli prontamente? –

+3

@deft_code: Penso che Howard sia abbastanza onesto per correggere i bug senza esserne vergognato. ; -] – ildjarn

+3

@deft_code: sembra essere una tecnica ad effetto. ;-) –