¿Hacer tipos de clase intercambiables solo a través de la conversión de punteros, sin tener que asignar ningún objeto nuevo?

ACTUALIZAR: Aprecio las sugerencias "no quiero eso, quiero esto". Son útiles, especialmente cuando se proporcionan en el contexto de laescenario motivador. Aún así ... independientemente de la bondad / maldad, tengo curiosidad por encontrar un disco duro y rápido"Sí, eso se puede hacer legalmente en C ++ 11" vs"no, no es posible hacer algo así".

Quiero "alias" un puntero de objeto como otro tipo, para elúnico propósito de añadir algunos métodos de ayuda. El alias no puede agregar miembros de datos a la clase subyacente (de hecho, ¡cuanto más puedo evitar que eso suceda, mejor!) Todos los alias son igualmente aplicables a cualquier objeto de este tipo ... es útil si el sistema de tipos puede sugerir cuál Es probable que el alias sea el más apropiado.

No debe haber información sobre ningún alias específico que alguna vez esté codificado en el objeto subyacente. Por lo tanto, creo que deberías poder "engañar" al sistema de tipos y dejar que sea una anotación ... verificada en el momento de la compilación, pero en última instancia es irrelevante para el lanzamiento en tiempo de ejecución. Algo a lo largo de estas líneas:

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

Bajo el capó, el método de fábrica es en realidad hacer unNodeBase clase, y luego utilizando un similarreinterpret_cast para devolverlo comoNode<AccessorFoo>*.

La manera fácil de evitar esto es hacer que estas clases ligeras que envuelven nodos y se transmiten por valor. Por lo tanto, no necesita la conversión, solo las clases de Accessor que toman el controlador de nodo para envolver en su constructor:

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

Pero si no tengo que pagar por todo eso, no quiero hacerlo. Eso implicaría, por ejemplo, hacer un tipo de acceso especial para cada tipo de puntero envuelto (AccessorFooShared, AccessorFooUnique, AccessorFooWeak, etc.) Es preferible tener estos punteros escritos con un alias para una sola identidad de objeto basada en punteros, y proporciona una buena ortogonalidad.

Así que volvamos a esa pregunta original:

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

Parece que habría alguna forma de hacer esto que podría ser fea pero no "romper las reglas". De acuerdo aISO14882: 2011 (e) 5.2.10-7:

Un puntero de objeto puede convertirse explícitamente en un puntero de objeto de un tipo diferente.70 Cuando un prvalue v del tipo "puntero a T1" se convierte al tipo "puntero a cv T2", el resultado es static_cast (static_cast (v)) si T1 y T2 son tipos de diseño estándar (3.9) y los requisitos de alineación de T2 no son más estrictos que los de T1, o si cualquiera de los tipos es nulo. Convertir un prvalor de tipo "puntero a T1" al tipo "puntero a T2" (donde T1 y T2 son tipos de objeto y donde los requisitos de alineación de T2 no son más estrictos que los de T1) y de nuevo a su tipo original, se obtiene el original valor del puntero El resultado de cualquier otra conversión de puntero no está especificado.

Profundizando en la definición de un"clase de diseño estándar", encontramos:

no tiene miembros de datos no estáticos de tipo clase de diseño no estándar (o matriz de tales tipos) o referencia, yno tiene funciones virtuales (10.3) ni clases base virtuales (10.1), ytiene el mismo control de acceso (cláusula 11) para todos los miembros de datos no estáticos, yno tiene clases base de diseño no estándar, yo no tiene un miembro de datos no estáticos en la clase más derivada y, como máximo, una clase base con miembros de datos no estáticos, o no tiene clases base con miembros de datos no estáticos, yno tiene clases base del mismo tipo que el primer miembro de datos no estáticos.

Parece que trabajar con algo como esto ataría mis manos un poco sin métodos virtuales en los accesores o el nodo. Sin embargo, C ++ 11 aparentemente tienestd::is_standard_layout para mantener las cosas controladas.

¿Se puede hacer esto con seguridad? Parece funcionar en gcc-4.7, pero me gustaría estar seguro de que no estoy invocando un comportamiento indefinido.

Respuestas a la pregunta(4)

Su respuesta a la pregunta