Largest / Smallest. Part 2

In the last post i showed you how to implement a ‘Largest’ traits template using pre-C++11.
In this post I will show you how to do the same using variadic templates.

First we declare the ‘bare’ template. It tells the compiler that ‘Largest’ take an unknown number of template parameters.

template <typename... Types>
struct Largest {};

Next, we create helper templates as we did before. In fact they are identical.

// Declaration.
template <const bool Boolean, typename TrueType, typename FalseType>
struct ChooseType;

// Specialisation for 'true'.
// Defines 'type' as 'TrueType'.
template <typename TrueType, typename FalseType>
struct ChooseType<true, TrueType, FalseType>
{
  typedef TrueType type;
};

// Specialisation for 'false'. 
// Defines 'type' as 'FalseType'.
template <typename TrueType, typename FalseType>
struct ChooseType<false, TrueType, FalseType>
{
  typedef FalseType type;
};

The main part of the template is very similar to before, but this time we just use the ellipsis as the type list.

typedef typename ChooseType<(sizeof(T1) > sizeof(typename Largest<Types...>::type)), // Boolean
                             T1,                                                     // TrueType
                             typename Largest<Types...>::type>                       // FalseType
                             ::type type;                                            // The largest type of the two.

Finally, as before we need a ‘stopper’ definition to tell the compiler when we’ve reached the end.

template <typename T1>
struct Largest<T1>
{
  typedef T1 type;
};

Putting it all together again we get…

template <typename... Types>
struct Largest {};

template <typename T1, typename... Types>
struct Largest<T1, Types...>
{
private:

  // Declaration.
  template <const bool Boolean, typename TrueType, typename FalseType>
  struct ChooseType;

  // Specialisation for 'true'.
  // Defines 'type' as 'TrueType'.
  template <typename TrueType, typename FalseType>
  struct ChooseType<true, TrueType, FalseType>
  {
    typedef TrueType type;
  };

  // Specialisation for 'false'. 
  // Defines 'type' as 'FalseType'.
  template <typename TrueType, typename FalseType>
  struct ChooseType<false, TrueType, FalseType>
  {
    typedef FalseType type;
  };

public:

  // Set 'type' to be the largest of the first parameter and any of the others.
  // This is recursive.
  typedef typename ChooseType<(sizeof(T1) > sizeof(typename Largest<Types...>::type)), // Boolean
                               T1,                                                     // TrueType
                               typename Largest<Types...>::type>                       // FalseType
                               ::type type;                                            // The largest type of the two.                                        
};

template <typename T1>
struct Largest<T1>
{
  typedef T1 type;
};

How It’s Used

template typename T1, typename T2, typename T3>
struct Buffer
{
  char buffer[sizeof(typename Largest<T1, T2, T3>::type)];
};

This variation has the advantage that it can handle any number of type, up to the capacity of the compiler.

You no doubt see that an additional template to handle smallest should be a trivial task.
Other additions to the templates could include the min/max size and alignment as traits.

John Wellbelove

John Wellbelove

Director of Aster Consulting Ltd
United Kingdom
I have been involved in technology and computer systems for all of my working life and have amassed considerable knowledge of designing and implementing systems that are both performant and correct. My role normally encompasses the entire project life-cycle, from specification to maintenance phase. Most systems I have worked on have required high speed and deterministic performance, often within a highly constrained platform. I am experienced in designing and adapting algorithms to solutions that are both space and time efficient, avoiding the normal overheads of standard solutions. Acting as a mentor for colleagues has often been a significant, though unofficial, part of my role.

I administer an open source project on Github.
See http://www.etlcpp.com/

Leave a Reply

Your email address will not be published. Required fields are marked *