Tornar os tipos de classe intercambiáveis ​​apenas por meio de conversão de ponteiro, sem precisar alocar novos objetos?

ATUALIZAR: Eu aprecio "não quero isso, quero isso em vez disso" sugestões. Eles são úteis, especialmente quando fornecidos no contexto dacenário motivador. Ainda assim ... independentemente de bondade / maldade, fiquei curioso para encontrar um disco rígido e rápido"sim, isso pode ser feito legalmente em C ++ 11" vs"não, não é possível fazer algo assim".

Eu quero "alias" um ponteiro de objeto como outro tipo, para oúnico propósito de adicionar alguns métodos auxiliares. O alias não pode adicionar membros de dados à classe subjacente (na verdade, quanto mais eu puder evitar que isso aconteça, melhor!) Todos os aliases são igualmente aplicáveis ​​a qualquer objeto desse tipo ... é apenas útil se o sistema de tipos puder sugerir qual alias é provavelmente o mais adequado.

Não deve haver informações sobre qualquer alias específico que já tenha sido codificado no objeto subjacente. Por isso, eu sinto que você deveria ser capaz de "trapacear" o sistema de tipos e apenas deixá-lo ser uma anotação ... verificada em tempo de compilação, mas em última análise irrelevante para o casting de tempo de execução. Algo ao longo destas linhas:

Node<AccessorFoo>* fooPtr = Node<AccessorFoo>::createViaFactory();
Node<AccessorBar>* barPtr = reinterpret_cast< Node<AccessorBar>* >(fooPtr);

Sob o capô, o método de fábrica está realmente fazendoNodeBase classe e, em seguida, usando um semelhantereinterpret_cast para devolvê-lo como umNode<AccessorFoo>*.

A maneira fácil de evitar isso é fazer com que essas classes leves envolvam nós e sejam passadas por valor. Portanto, você não precisa converter, apenas classes Accessor que usam o identificador de nó para incluir em seu construtor:

AccessorFoo foo (NodeBase::createViaFactory());
AccessorBar bar (foo.getNode());

Mas se eu não tiver que pagar por tudo isso, não quero. Isso envolveria - por exemplo - fazer um tipo de acessor especial para cada tipo de ponteiro empacotado (AccessorFooShared, AccessorFooUnique, AccessorFooWeak, etc.). É preferível ter esses ponteiros tipados com alias para uma única identidade de objeto baseada em ponteiro, e fornece uma boa ortogonalidade.

Então, de volta à pergunta original:

Node<AccessorFoo>* fooPtr = Node<AccessorFoo>::createViaFactory();
Node<AccessorBar>* barPtr = reinterpret_cast< Node<AccessorBar>* >(fooPtr);

Parece que haveria alguma maneira de fazer isso que pode ser feio, mas não "quebrar as regras". De acordo comISO14882: 2011 (e) 5.2.10-7:

Um ponteiro de objeto pode ser explicitamente convertido em um ponteiro de objeto de um tipo diferente.70 Quando um prvalor v do tipo "pointer to T1" é convertido para o tipo "pointer to cv T2", o resultado é static_cast (static_cast (v)) se T1 e T2 forem tipos de layout padrão (3.9) e os requisitos de alinhamento de T2 não forem mais rigorosos que os de T1, ou se algum dos tipos for vazio. Convertendo um prvalor do tipo "pointer para T1" para o tipo "pointer to T2" (onde T1 e T2 são tipos de objeto e onde os requisitos de alinhamento de T2 não são mais rigorosos que os de T1) e de volta ao seu tipo original produz o original valor do ponteiro. O resultado de qualquer outra conversão de ponteiro não é especificado.

Perfurando a definição de um"classe de layout padrão", nós achamos:

não possui membros de dados não estáticos do tipo não-padrão-layout-classe (ou matriz de tais tipos) ou referência, enão possui funções virtuais (10.3) e nenhuma classe base virtual (10.1), etem o mesmo controle de acesso (cláusula 11) para todos os membros de dados não estáticos, enão possui classes base de layout não padrão eou não possui nenhum membro de dados não estático na classe mais derivada e no máximo uma classe base com membros de dados não estáticos, ou não possui classes base com membros de dados não estáticos enão possui classes base do mesmo tipo que o primeiro membro de dados não estáticos.

Parece que trabalhar com algo assim ligaria minhas mãos um pouco sem métodos virtuais nos acessores ou no nó. Ainda C ++ 11 aparentemente temstd::is_standard_layout para manter as coisas verificadas.

Isso pode ser feito com segurança? Parece funcionar no gcc-4.7, mas gostaria de ter certeza de que não estou invocando um comportamento indefinido.

questionAnswers(4)

yourAnswerToTheQuestion