Search code examples
c++stlgeneric-programming

Inheritance & virtual functions Vs Generic Programming


I need to Understand that whether really Inheritance & virtual functions not necessary in C++ and one can achieve everything using Generic programming. This came from Alexander Stepanov and Lecture I was watching is Alexander Stepanov: STL and Its Design Principles


Solution

  • I always like to think of templates and inheritance as two orthogonal concepts, in the very literal sense: To me, inheritance goes "vertically", starting with a base class at the top and going "down" to more and more derived classes. Every (publically) derived class is a base class in terms of its interface: A poodle is a dog is an animal.

    On the other hand, templates go "horizontal": Each instance of a template has the same formal code content, but two distinct instances are entirely separate, unrelated pieces that run in "parallel" and don't see each other. Sorting an array of integers is formally the same as sorting an array of floats, but an array of integers is not at all related to an array of floats.

    Since these two concepts are entirely orthogonal, their application is, too. Sure, you can contrive situations in which you could replace one by another, but when done idiomatically, both template (generic) programming and inheritance (polymorphic) programming are independent techniques that both have their place.

    Inheritance is about making an abstract concept more and more concrete by adding details. Generic programming is essentially code generation.

    As my favourite example, let me mention how the two technologies come together beautifully in a popular implementation of type erasure: A single handler class holds a private polymorphic pointer-to-base of an abstract container class, and the concrete, derived container class is determined a templated type-deducing constructor. We use template code generation to create an arbitrary family of derived classes:

    // internal helper base
    class TEBase { /* ... */ };
    
    // internal helper derived TEMPLATE class (unbounded family!)
    template <typename T> class TEImpl : public TEBase { /* ... */ }
    
    // single public interface class
    class TE
    {
      TEBase * impl;
    public:
      // "infinitely many" constructors:
      template <typename T> TE(const T & x) : impl(new TEImpl<T>(x)) { }
      // ...
    };