2011-12-19 29 views
12

Poniższy kod kompiluje się z brzękiem 3,0/libC++:std :: make_shared STD :: unique_ptr i przenieść konstruktorzy

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

Ale to nie (std::string parametr dodane):

#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 skarży się na użycie usuniętego konstruktora. Dla mnie to nie ma sensu, ponieważ std::make_shared nie powinno kopiować instancji Foo, jedynej rzeczy, która wyzwala wywołanie konstruktora kopiowania (usuniętego) z std::unique_ptr.

Ale zaraz po tym jak zdefiniuję konstruktor ruchu jawnie, kompiluje.

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

Teraz pytania:

  1. Dlaczego kompilować w pierwszym przykładzie, ale nie drugi?
  2. Czy można skopiować/przenieść obiekt podczas jego tworzenia?
  3. Dlaczego dodanie konstruktora ruchu rozwiązuje problem? Nie przypominam sobie, że dodanie innego niż domyślny konstruktora powinno powstrzymać niejawny konstruktor ruchu.

EDIT: sprawdzone i wszystkie przykłady wydają się skompilować grzywny z gcc 4.5.1 (przez ideone.com), podejrzewam, że jest to przypadek Clang/libC++ bug, ale pytania 2 i 3 nadal stoją, plus chciałbym wiedzieć, który kompilator jest bardziej "poprawny".

+1

Nie sądzę, istnieje coraz niejawny konstruktor ruch warunkiem –

+0

@parapura Rajkumar (1) usunięcie unique_ptr sprawia, że ​​odejdzie (nawet z non-default ctor), (2) niejawny konstruktor ruchu jest nadal definiowany zgodnie z najnowszym brzmieniem: http: //mmocny.wordpress.com/2010/12/09/implicit-move-wont-go/ –

+0

@parapurarajkumar: rzeczywiście, przypominam sobie, że czytałem dyskusje, w których niejawni konstruktorzy ruchu byli złymi rzeczami i powinni zostać usunięci ze standardu. Jednak nie znam końca historii. –

Odpowiedz

20

Dlaczego kompiluje się w pierwszym przykładzie, ale nie w drugim?

To jest błąd biblioteki libC++. Pracuję nad poprawką teraz ...

Czy std :: make_shared kopiuje/przenosi obiekt podczas jego tworzenia?

Nie, nie wierzę w to.

Dlaczego dodanie konstruktora ruchu rozwiązuje problem? Nie pamiętam, , że dodawanie innych niż domyślny konstruktor powinien ukryć domyślny konstruktor ruchu .

W wersji clang, której używasz, domyślne konstruktory ruchu nie są jeszcze zaimplementowane.

Aktualizacja

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

+5

Wow! godzina na odwrót! Więc jeśli znajdziemy inne błędy w clang/libC++, możemy po prostu opublikować je w Stackoverflow, aby zawstydzić was do szybkiego ich naprawienia? –

+3

@deft_code: Myślę, że Howard jest na tyle uczciwy, aby naprawiać błędy bez wstydzeń. ; -] – ildjarn

+3

@deft_code: To wydaje się być techniką efektu. ;-) –

Powiązane problemy