Topical Information

The purpose of this quiz is to give you a chance to focus your knowledge of advanced template usage in C++.

Quiz Information

Questions

  1. Briefly explain the use of non-type template parameters. (Perhaps a specific example might help...

    
        Where we normally list typenames to be specified to or deduced by the
        compiler, we may also place discrete types which are to be filled in
        with a value.
    
        This can be used, for instance, to create many classes for an array of
        arbitrary dimensions -- each dimensionality being its own separate
        class.
    
        We could also use it to build a templated swap function for C-style
        arrays by making the common allocated size of the two arguments the
        template's non-type parameter.  (Of course, we'd also have to use a
        reference trick to bind the size to the array argument since any
        listed size for a 1D array argument is normally ignored by the
        compiler!)
    
    
  2. Briefly describe the difference between overloading a template and specializing a template.

    
        An overloaded template is still not instantiated but, rather, merely
        gives the compiler multiple blank patterns to match against.  It
        will still choose the pattern that most specifically matches the
        current invocation thanks to SFINAE (Substitution Failure Is Not
        An Error).
    
        With specialization, however, a template has its existing typenames
        partially or fully filled in with specific data types.  (Or its
        non-type parameters may be filled in with specific values.) This
        creates a new instantiation for the template pattern which is
        inherently more specific than the template itself.
    
        Either way you go, typecasting can help at the call site to make
        sure the right form of the function is called.  This works best
        because it doesn't matter if the function is a template or not, the
        compiler just uses the right types.
    
    
  3. Below are two designs for a templated Sum class that can add up a sequence of values to a total and then retrieve that total later. In each case, the types of the items being summed don't have to be the same as those of the sum itself. What is the difference between the two and what might the benefit of this difference be?

    Consider not only adding up numbers but also concatenating strings.

        template <typename SumType, typename ItemType>
        class Sum
        {
            SumType sum;
        public:
            Sum(const ItemType & s = ItemType()) { sum = s; }
            Sum(const Sum & s) { sum = s.sum; }
            SumType operator() (const ItemType & n) { return sum += n; }
            SumType operator() (void) { return sum; }
            void reset(const ItemType & s = ItemType()) { sum = s; return; }
        };
    
        template <typename SumType>
        class Sum
        {
            SumType sum;
        public:
            Sum(const SumType & s = SumType()) { sum = s; }
            Sum(const Sum & s) { sum = s.sum; }
            template <typename ItemType>
            SumType operator() (const ItemType & n) { return sum += n; }
            SumType operator() (void) { return sum; }
            void reset(const SumType & s = SumType()) { sum = s; return; }
        };
    
    
        The first Sum class requires all of the elements being added to the sum
        to be of the same type -- a homogeneous sequence.  The second Sum class
        allows the elements being added at each step to be of different types
        from those before/after them -- a heterogeneous sequence.
    
        The second approach can be more flexible in cases where we want to add
        up numbers of different types through the course of the program or even
        add up both strings, C-strings, and characters at different points in a
        program.
    
    
  4. If we were for some reason defining the second Sum class' summing operator() not inline, show how this would look.

    
        template <typename SumType>
        template <typename ItemType>
        SumType Sum<SumType>::operator() (const ItemType & n)
        {
            return sum += n;
        }
    
        Note how we had to nest the ItemType template inside the SumType
        template rather than merging them together.  Also note that the
        scope of the operator just has the SumType involved.
    
    
  5. Now let's consider templates mixed with inheritance:

     
    TRUE   FALSE   A base class cannot be a template class.
    TRUE   FALSE   A derived class can be a template class.
    TRUE   FALSE   If we derive from a template class, the new class must be a template, too.
    TRUE   FALSE   If we derive from a non-template class, the new class must be a non-template, too.
  6.  
    TRUE   FALSE   When a template class has static member(s), all instantiations share the same static member(s).