Monday, January 30, 2017

D - Templates

Templates are the foundation of generic programming, which involves writing code in a way that is independent of any particular type.
A template is a blueprint or formula for creating a generic class or a function.

Templates are the feature that allows describing the code as a pattern, for the compiler to generate program code automatically. Parts of the source code may be left to the compiler to be filled in until that part is actually used in the program. The compiler fills in the missing parts.

Function Template:

Defining a function as a template is leaving one or more of the types that it uses as unspecified, to be deduced later by the compiler. The types that are being left unspecified are defined within the template parameter list, which comes between the name of the function and the function parameter list. For that reason, function templates have two parameter lists: the template parameter list and the function parameter list:
import std.stdio;

void print(T)(T value)
{
   writefln("%s", value);
}

void main()
{
   print(42);

   print(1.2);

   print("test");
}
If we compile and run above code, this would produce the following result:
42
1.2
test

Function Template with multiple type parameters

There can be multiple parameter types and it is shown is shown in the following example.
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);
}
If we compile and run above code, this would produce the following result:
 42 Test
 1.2 33

Class Templates

Just as we can define function templates, we can also define class templates. Following is the example to define class Stack and implement generic methods to push and pop the elements from the stack.
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);
}
If we compile and run above code, this would produce the following result:
Test2
2
Test1
1

No comments:

Post a Comment