2015-02-22 18 views
15

W szczególności w związku z std::vector ważne jest, aby typy były ruchome, o ile to możliwe.Jakie są zasady dotyczące noexcept w domyślnych zdefiniowanych konstruktorach ruchu?

więc podczas deklarowania konstruktora ruch = default jak w

struct Object1 
{ 
    Object1(Object1 &&other) = default; 
}; 

std::is_nothrow_move_constructible<Object1>::value będzie true jak każdego członka (0 tutaj) od Object1 jest nothrow-move-constructible, który odpowiedział here.

Co się stanie, jeśli konstruktor kopiowania ruchu zostanie zadeklarowany, a następnie zdefiniowany jako = default jak w poniższym kodzie?

struct Object2 
{ 
    Object2(Object2 &&other); 
}; 
Object2::Object2(Object2 &&other) = default; 

Z g ++ 4.9.2 std::is_nothrow_move_constructible<Object2>::value jest false i muszę zaznaczyć zarówno deklaracji i definicji jako noexcept aby to true.

Teraz interesują mnie rzeczywiste zasady. Zwłaszcza, że ​​Pozycja 22 w Effective Modern C++ (Scott Meyers) wydaje się udzielać złych rad, sugerując implementację konstruktora ruchu pimpl-idiom, tak jak zrobiłem to z Object2.

Odpowiedz

11

[dcl.fct.def.default]/p2:

Jeśli funkcja jest wyraźnie wywiąże się ze swoim pierwszym oświadczeniu

  • jest domyślnie uznawane za constexpr jeśli niejawna deklaracja będzie, i,
  • ma tę samą specyfikację wyjątków, jak gdyby została domyślnie zadeklarowana (15.4).

Te zasady nie stosuje się, jeżeli funkcja jest wyraźnie zaległości w późniejszym deklaracji, jak w późniejszym przykład, więc zamiast tego, z wyjątkiem destruktorów, funkcja jest uważana noexcept(false) domyślnie jak większość innych funkcji.

Ponieważ wyraźny zalegających może być w innej jednostce tłumaczeniowej - aw przypadku pimpl, jest w innym TU - nie ma ogólny sposób kompilator, aby dowiedzieć się, po obejrzeniu definicję klasy tylko, czy konstruktor posunięcie wyrzuci, chyba że funkcja jest jawnie domyślna w definicji klasy (tj. przy pierwszej deklaracji).