Saturday, July 23, 2016

m Template notions only..:-)

The materials followed below are all cited from [K Hong]

Templates

We use templates when we need functions/classes that apply the same algorithm to a several types. So we can use the same function/class regardless of the types of the argument or result.


In other words, a template is a mechanism that allows a programmer to use types as parameters for a class or a function. The compiler then generates a specific class or function when we later provide specific types as arguments. In a sense, templates provide static (compile-time) polymorphism, as opposed to dynamic (run-time) polymorphism. A function/class defined using template is called a generic function/class, and the ability to use and create generic functions/classes is one of the key features of C++.
We can think of a class template as a type generator. The process of generating types from a class template is called specialization or template instantiation.
In most of the cases, template instantiation is very complicated, but that complexity is in the domain of compiler writer, not the template user. Template instantiation takes place at compile time or link time, not at run time.
......
Templates are the foundation of generic programming. Generic programming relies on polymorphism. Though there are several differences between OOP (class hierarchies and virtual functions) and generic programming (templates), the major difference is:
  1. Generic (templates) : compile time resolution. 
    The choice of function invoked when we use is determined by the compiler at compile time.
  2. OOP (virtual functions) : run time resolution.
Generic programming lets us write classes and functions that are polymorphic across unrelated types at compile time. A single class or function can be used to manipulate objects of a variety of types. The standard library containers, iterators, and algorithms are examples of generic programming. We can use library classes and functions on any kind of type.
When we parameterize a class, we get a class template, and when we parameterize a function, we get a function template.
So, what do people actually use template for?
  1. When performance is essential.
  2. When flexibility in combining information from several types is essential.
But note that, the flexibility and performance come at the cost of poor error diagnostics and poor error messages.
......

Terminology of Templates

Let's review the terminology of template using the following example implementing a generic stack class. This section of terminology is borrowed from "API design for C++" by Martin Reddy, 2011.
template <typename T>
class Stack
{
public:
 void push(T val);
 T pop();
 bool isEmpty() const;
private:
 std:vector<T> mStack;
};
  1. Template Parameters
    These names are listed after the template keyword in a template declarations. As shown in the example, T is the single template parameter specified in the Stack class....[Template Parameters]
  2. Template Arguments
    These are substituted for template parameters during specialization. In our example, given a specialization Stack<int>, the int is a template argument....[Type Parameters]
  3. Instantiation
    This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type. This can happen implicitly when we create an object based on a template or explicitly if we want to control when the code generation happens. For instance, the following code creates two specific stack instances and will normally cause the compiler to generate code for these two different types:
    Stack<T> myIntStack;
    Stack<T> myStringStack;
    
  4. Implicit Instantiation
    This is when the compiler decides when to generate code for our template instances. Leaving the decision to the compiler means that it must find an appropriate place to insert the code, and it must also make sure that only one instance of the code exists to avoid duplicate symbol errors. This is non-trivial problem and can cause extra bloat in our object files or longer compile time. Most importantly, implicit instantiation means that we have to include the template definitions in our header files so that the compiler has an access to the definitions whenever it needs to generate the instantiation code.
  5. Emplicit Instantiation
    This is when the programmer determine when the compiler should generate the code for a specific specialization. This can make for much more efficient compilation and link times because the compiler no longer needs to maintain bookkeeping information for all of its implicit instantiations. The onus, however, is then placed on the programmer to ensure that a particular specialization is explicitly instantiated only once. So, explicit instantiation allows us to move the template implementation into the .cpp file, and so hide from the user.
  6. Lazy Instantiation
    This describes the standard implicit instantation behavior of a C++ compiler wherein it will only generate code for the parts of a template that are actually used. Given the previous two instantiations, for example, if we never called isEmpty() on themyStringStack object, then the compiler would not generate code for the std::stringspecialization of that method. This means that we can instantiate a template with a type that can be used by some, but not all methods of a class template. If one method uses the >= operator, but the type we want to instantiate does not define this operator. This is fine as long as we don't call the particular method that attempts to use the >= operator.
  7. Specialization
    When a template is instantiated, the resulting class, method, or function is called a specialization. More specifically, this is an instantiated (or generated) specialization. However, the term specialization can also be used when we provide a custom implementation for a function by specifying concrete types for all the template parameters. The following is called an explicit specialization:
    tempate<>
    void Stack<int>::push(int val)
    {
        // integer specific push implementation
    }
    
  8. Partial Specialization
    This is when we provide a specialization of the template for a subset of all possible cases. In other words, we specialize one feature of the template but still allow the user to specify other features. For example, if our template accepts multiple parameters, we could partially specialize it by defining a case where we specify a concrete type for only one of the parameters. In our Stack example with a single template parameter, we could partially specialize this template to specifically handle pointers(*) to any type T. This still lets users create a stack of any type, but it also lets us write specific logic to handle the case where users create a stack of pointers. This partially specialized class declaration looks like this:
    template <typename T>
    class Stack<T*>
    {
    public:
     void push(T* val);
     T* pop();
     bool isEmpty() const;
    private:
     std:vector<T*> mStack;
    };
    
.......

Pros and Cons of Templates


  1. Pros
    1. It provides us type-safeefficient generic containers and generic algorithms
    2. The main reason for using C++ and templates is the trade-offs in performance and maintainability outweigh the bigger size of the resulting code and longer compile times.
    3. The drawbacks of not using them are likely to be much greater.
  2. Cons
    1. Templates can lead to slower compile-times and possibly larger executable.
    2. Compilers often produce incomprehensible poor error diagnostics and poor error messages.
    3. The design of the STL collections tends to lead to a lot of copying of objects. The original smart pointer, std::auto_ptr, wasn't suitable for use in most collections. Things could be improved if we use other smart pointers from boost or C11.
......


No comments:

Post a Comment