Dos años después entiendo la situación mucho mejor, en interés de mantener las respuestas de desbordamiento de pila relevantes y actualizadas aquí es cómo respondería la pregunta hoy.
La premisa de mi pregunta original es algo defectuosa. La razón para usar el idioma pimpl es ocultar los detalles de implementación del compilador. Esto se hace almacenando la implementación a través de un puntero opaco (puntero a un tipo de datos declarado pero no definido). Esto puede reducir en gran medida la cantidad de encabezados necesarios para otras unidades de compilación que interactúan con la clase y así acelerar el tiempo de compilación. En el caso de la plantilla en mi pregunta, se requiere que el tipo T sea completamente conocido en el momento de la creación de instancias, lo que en la práctica requiere que el tipo impl esté completamente definido dondequiera que se use C<ImplType>
, haciendo esto claramente no un ejemplo del idioma pimpl en el sentido clásico del término.
Existen otras razones para mantener datos de clases a través de un puntero privado, por ejemplo, permite una fácil implementación de movimiento e intercambio de no-throw y también es bueno si su clase necesita cumplir una fuerte garantía de excepción (ver copia y swap idiom What is the copy-and-swap idiom?). Por otro lado, agrega una capa de direccionamiento indirecto (que a menudo resulta en una falta de caché) en cada acceso al impl y una asignación/desasignación de un montón al crear y destruir el impl.Estas pueden ser sanciones de rendimiento sustanciales, por lo tanto, esta solución no debe considerarse una solución milagrosa.
Si puede usar C++ 11, se debe usar std :: unique_ptr en lugar de boost :: scoped_ptr.
Este tipo de implementación PIMPL no tiene ningún sentido porque para crear una instancia de la plantilla C, debe conocer el tipo T. PIMPL, por otro lado, oculta completamente el equivalente de T del usuario. –
@VladLazarenko Hmm, pensé impulso :: scoped_ptr funciona tan bien en las clases predeclared. En este caso, depende si T está definido o predeclamado. La instanciación de este scoped_ptr estaría oculta en la implementación (pimpl_ (new T()). –
@DavidFeurle: En realidad, para que esta plantilla funcione, el tamaño de 'T', así como su interfaz, debe ser expuesto, porque los "clientes" necesitan crear una instancia de la plantilla. Por ejemplo, ¿a dónde llama 'nueva T()'? No puede ocultar eso en el archivo "cpp" porque debe estar en la plantilla. Por lo tanto, no es PIMPL. –