Using Arguments to Specify Policy

Using Arguments to Specify Policy

Consider the earlier sort function template:

//
//  templbubble.h
//  Function Templates
//
//  Created by Bryan Higgs on 10/11/24.
//

#ifndef templbubble_h
#define templbubble_h

#include <vector>

template<typename TYPE>
void sort(std::vector<TYPE> &v)
{
  size_t n = v.size();
  for (size_t i = 0; i < n - 1; i++)
  {
    for (size_t j = n - 1; i < j; j--)
    {
      if (v[j] < v[j - 1])
      {  // swap v[j] and v[j-1]
        TYPE temp = v[j];
        v[j] = v[j-1];
        v[j - 1] = temp;
      }
    }
  }
}

#endif /* templbubble_h */

What if we wanted to sort strings based on some other kind of collating sequence?  For example, in a case-insensitive order, or in reverse order.

The sort algorithm doesn’t change.  Only the comparison needs to change from:

if (v[j] < v[j - 1])

We simply need to generalize this to a compare operation, and then provide a mechanism to pass in the desired compare operation.

//
//  PolicySort.h
//  Function Overload Resolution
//
//  Created by Bryan Higgs on 10/13/24.
//

#ifndef PolicySort_h
#define PolicySort_h

#include <vector>

template<typename TYPE, typename C>
void sort(std::vector<TYPE> &v)
{
  size_t n = v.size();
  for (size_t i = 0; i < n - 1; i++)
  {
    for (size_t j = n - 1; i < j; j--)
    {
      if (C::compare(v[j], v[j - 1]) < 0)
      {  // swap v[j] and v[j-1]
        TYPE temp = v[j];
        v[j] = v[j-1];
        v[j - 1] = temp;
      }
    }
  }
}

#endif /* PolicySort_h */

Here’s a class, Compare, with the necessary compare() class function:

//
//  PolicyCompare.h
//  Function Overload Resolution
//
//  Created by Bryan Higgs on 10/13/24.
//

#ifndef PolicyCompare_h
#define PolicyCompare_h

// A 'policy' class
class Compare
{
public:
  static int compare(const char *s1, const char *s2)
  {
    return strcmp(s1, s2);  // compare in the normal way
  }
};

#endif /* PolicyCompare_h */

Finally, here’s a main program to exercise this:

//
//  PolicySort.cpp
//  Function Overload Resolution
//
//  Created by Bryan Higgs on 10/13/24.
//

#include <iostream>
#include "PolicySort.h"
#include "PolicyCompare.h"

void printVector(std::vector<const char *> v)
{
  for(int i = 0; i < v.size(); i++)
    std::cout << ' ' << v[i] << std::endl;
}

int main()
{
  std::vector<const char *> vstrs(10);
  
  vstrs[0] = "Vera";
  vstrs[1] = "mary";
  vstrs[2] = "fred";
  vstrs[3] = "Zena";
  vstrs[4] = "Algernon";
  vstrs[5] = "carol";
  vstrs[6] = "alan";
  vstrs[7] = "Richard";
  vstrs[8] = "Beatrice";
  vstrs[9] = "xavier";

  std::cout << "Before sorting: " << std::endl;
  printVector(vstrs);

  sort<const char *, Compare>(vstrs);
    
  std::cout << "After sorting: " << std::endl;
  printVector(vstrs);

  return 0;
}

… which produces the following:

Before sorting: 
 Vera
 mary
 fred
 Zena
 Algernon
 carol
 alan
 Richard
 Beatrice
 xavier
After sorting: 
 Algernon
 Beatrice
 Richard
 Vera
 Zena
 alan
 carol
 fred
 mary
 xavier
Program ended with exit code: 0

If we change the Compare class as follows:

//
//  PolicyCompare.h
//  Function Overload Resolution
//
//  Created by Bryan Higgs on 10/13/24.
//

#ifndef PolicyCompare_h
#define PolicyCompare_h

// A 'policy' class
class Compare
{
public:
  static int compare(const char *s1, const char *s2)
  {
    return -strcmp(s1, s2);	// reverse compare
  }
};

#endif /* PolicyCompare_h */

Now, the program outputs the reversed sort order:

Before sorting: 
 Vera
 mary
 fred
 Zena
 Algernon
 carol
 alan
 Richard
 Beatrice
 xavier
After sorting: 
 xavier
 mary
 fred
 carol
 alan
 Zena
 Vera
 Richard
 Beatrice
 Algernon
Program ended with exit code: 0

Similarly, we could simply pass in a different class with a different compare implementation to control sorting order in any way we wish.