O que constitui um estado válido para um objeto “movido de” no C ++ 11?
Eu tenho tentado entender como a semântica de movimento em C ++ 11 deve funcionar, e estou tendo problemas para entender quais condições um objeto movido-a-objeto precisa satisfazer. Olhando para oresponda aqui realmente não resolve a minha questão, porque não consigo ver como aplicá-la aos objetos pimpl de uma maneira sensata, apesar dos argumentos quesemântica de movimento são perfeitos para pimpls.
A ilustração mais fácil do meu problema envolve o idioma pimpl, assim:
class Foo {
std::unique_ptr<FooImpl> impl_;
public:
// Inlining FooImpl's constructors for brevity's sake; otherwise it
// defeats the point.
Foo() : impl_(new FooImpl()) {}
Foo(const Foo & rhs) : impl_(new FooImpl(*rhs.impl_)) {}
Foo(Foo && rhs) : impl_(std::move(rhs.impl_)) {}
Foo & operator=(Foo rhs)
{
std::swap(impl_, rhs.impl_);
return *this;
}
void do_stuff ()
{
impl_->do_stuff;
}
};
Agora, o que posso fazer depois de mudar de umFoo
? Eu posso destruir o objeto movido de forma segura, e posso atribuir a ele, ambos os quais são absolutamente cruciais. No entanto, se eu tentardo_stuff
com minhaFoo
, vai explodir. Antes eu adicionei a semântica de movimento para minha definição deFoo
, cadaFoo
satisfeito o invariável que poderiado_stuff
e isso não é mais o caso. Não parece haver muitas alternativas excelentes, já que (por exemplo) colocar o movido deFoo
envolveria uma nova alocação dinâmica, que parcialmente anula o propósito de mover a semântica. Eu poderia verificar seimpl_
emdo_stuff
e inicializá-lo para um padrãoFooImpl
se for, mas isso adiciona um cheque (geralmente espúrio), e se eu tiver muitos métodos significaria lembrar de fazer o check-in em cada um.
Devo desistir da ideia de que ser capaz dedo_stuff
é uma invariante razoável?