Programación D - Plantillas

Las plantillas son la base de la programación genérica, que implica escribir código de una manera que es independiente de cualquier tipo en particular.

Una plantilla es un plan o fórmula para crear una clase o función genérica.

Las plantillas son la característica que permite describir el código como un patrón, para que el compilador genere el código del programa automáticamente. Se pueden dejar partes del código fuente al compilador para que las complete hasta que esa parte se use realmente en el programa. El compilador completa las partes que faltan.

Plantilla de función

Definir una función como plantilla es dejar uno o más de los tipos que utiliza sin especificar, para que el compilador los deduzca más adelante. Los tipos que se dejan sin especificar se definen dentro de la lista de parámetros de la plantilla, que se encuentra entre el nombre de la función y la lista de parámetros de la función. Por esa razón, las plantillas de funciones tienen dos listas de parámetros:

  • lista de parámetros de plantilla
  • lista de parámetros de función
import std.stdio; 
 
void print(T)(T value) { 
   writefln("%s", value); 
}
  
void main() { 
   print(42);  
   
   print(1.2);
   
   print("test"); 
}

Si compilamos y ejecutamos el código anterior, esto produciría el siguiente resultado:

42 
1.2 
test

Plantilla de función con varios parámetros de tipo

Puede haber varios tipos de parámetros. Se muestran en el siguiente ejemplo.

import std.stdio;
  
void print(T1, T2)(T1 value1, T2 value2) { 
   writefln(" %s %s", value1, value2); 
}

void main() { 
   print(42, "Test");  
   
   print(1.2, 33); 
}

Si compilamos y ejecutamos el código anterior, esto produciría el siguiente resultado:

42 Test 
 1.2 33

Plantillas de clase

Así como podemos definir plantillas de funciones, también podemos definir plantillas de clases. El siguiente ejemplo define la clase Stack e implementa métodos genéricos para empujar y sacar los elementos de la pila.

import std.stdio; 
import std.string; 
 
class Stack(T) { 
   private: 
      T[] elements;  
   public:  
      void push(T element) { 
         elements ~= element; 
      }
      void pop() { 
         --elements.length; 
      } 
      T top() const @property { 
         return elements[$ - 1]; 
      }
      size_t length() const @property { 
         return elements.length; 
      } 
}
  
void main() { 
   auto stack = new Stack!string;
   
   stack.push("Test1"); 
   stack.push("Test2");  
   
   writeln(stack.top); 
   writeln(stack.length); 
   
   stack.pop; 
   writeln(stack.top); 
   writeln(stack.length); 
}

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

Test2 
2 
Test1 
1