Skip to content

Implementación de clases de políticas con parámetros de plantilla

Andres Angarita edited this page Dec 28, 2019 · 1 revision

A menudo, como es el caso anterior, el argumento de la plantilla de la política es redundante. Es incómodo que el usuario deba pasar el argumento de la plantilla OperatorNewCreator explicitamente. Normalmente, la clase de host ya conoce, o puede deducir facílmente, el argumento de plantilla de la clase de política. En el ejemplo anterior, MyWidgetMgr siempre maneja objetos de tipo Widget, por lo que requerir que el usuario especifique Widget nuevamente en la instancia de OperatorNewCreator es redundante y potencialmente peligroso.

En este caso, el código de la biblioteca puede usar parámetros de plantilla de plantilla para especificar políticas, como se muestra a continuación:

// Library code
template <template <class Created> class CreationPolicy>
class WidgetManager : public CreationPolicy<Widget> {
	...
};

A pesar de las apariencias, el símbolo Created no contribuye a la definición de WidgetManager. No puede usar Created dentro de WidgetManager: es un argumento formal para CreationPolicy y simplemente puede omitirse.

El código de la aplicación ahora solo necesita proporcionar el nombre de la plantilla al crear una instancia de WidgetManager:

// Application code
typedef WidgetManager<OperatorNewCreator> MyWidgetMgr;

Usar parámetros de plantilla de plantilla con clases de políticas no es simplemente una cuestión de conveniencia; a veces, es esencial que la clase de host tenga acceso a la plantilla para que el host pueda instanciar con un tipo diferente. Por ejemplo, suponga que WidgetManager también necesita crear objetos de tipo Gadget usando la misma política de creación. Entonces el código se vería así:

// Library code
template <template <class> class CreationPolicy>
class WidgetManager : public CreationPolicy<Widget> {
	...
	void DoSomething()	{
		Gadget* pW = CreationPolicy<Gadget>().Create();
		...
	}
};

¿El uso de políticas te da una ventaja? A primera vista, no mucho. Por un lado, todas las implementaciones de la política Creator son trivialmente simples. El autor de WidgetManager ciertamente podría haber escrito el código de creación en línea y evitar la molestia de hacer de WidgetManager una plantilla.

Pero el uso de políticas le da una gran flexibilidad a WidgetManager. Primero, puede cambiar las políticas desde el exterior tan facilmente como cambiar un argumento de plantilla cuando crea una instancia de WidgetManager. En segundo lugar, puede proporcionar sus propias políticas especificas de su aplicación concreta. Puede usar new, malloc, prototipos o una biblioteca de asignación de memoria peculiar que solo usa sus sistema. Es como si WidgetManager fuera un pequeño motor de generación de código, y usted configura las formas en que genera el código.

Para facilitar la vida de los desarrolladores de aplicaciones, el autor de WidgetManager podría definir una batería de políticas de uso frecuente y proporcionar un argumento de plantilla predeterminado para la política que se usa más comúnmente:

template <template <class> class CreationPolicy = OperatorNewCreator>
class WidgetManager ...

Tenga en cuenta que las políticas son bastante diferentes de las meras funciones virtuales. Las funciones virtuales prometen un efecto similar: el implementador de una clase define funciones de nivel superior en términos de funciones virtuales primitivas y permite al usuario anular el comportamiento de esas primitivas. Sin embargo, como se muestra arriba, las políticas vienen con conocimiento de tipo enriquecido y enlace estático, que son ingredientes esenciales para los diseños de edificios. ¿No están los diseños llenos de reglas que dictan antes del tiempo de ejecución cómo interactúan los tipos entre sí y que puedes y qué no puedes hacer? Las políticas le permiten generar diseños mediante la combinación de opciones simples de una manera segura. Además, debido a que el enlace entre una clase de host y sus políticas se realiza en tiempo de compilación, el código es escrito y eficiente, comparable a su equivalente artesanal.

Por supuesto, las características de las políticas también las hacen inadecuadas para el enlace dinámico y las interfaces binarias, por lo que, en esencia, las políticas y las interfaces clásicas no compiten.