CSCI 330 Lab 6: using C++ templates to create variadic and higher order functions

This semester we saw the use of variadic functions (functions that can accept any number of parameter) and higher order functions in common lisp.

Our objective in this lab is to use templates to create one C++ function that is variadic, another that is higher order, and one that is both variadic and higher order.

Objectives

Templates can be used in C++ to create higher order functions (an example is available in file higher.cpp in the examples subdirectory of the lab6 repo), and can be used to create variadic functions (an example is available in file variadic.cpp in the examples subdirectory of the repo).

We'll apply these approaches to create three sets of function templates in our lab6.h:

In our lab6.cpp we'll include lab6.h, declare a variety of functions to serve as the higher order parameters to aaaa and cccc, and set up a main routine to demonstrate that our three sets of function templates work correctly.


Specifications and design suggestions

We have three different functions to support, each implemented through a set of templates in the lab6.h file.

Some examples of calls to the three functions and the corresponding output are shown in the testing section below.


Testing

To demonstrate that your functions work correctly, include some standard (non-templated) function definitions and a main routine in your lab6.cpp that demonstrates calls to each of functions aaaa, bbbb, and cccc with different combinations of function/value pairs.

A basic lab6.cpp is shown below, illustrating a set of valid calls using our templated functions. Feel free to create your own test cases, you aren't required to use these ones.

#include "lab6.h"
#include <cmath>
#include <iostream>
#include <string>
using namespace std;

string concat(string s1, string s2)
{
   return s1+s2;
}

int smallInt(int x, int y)
{
   if (x < y) return x;
   else return y;
}

string smallStr(string s1, string s2)
{
   if (s1 < s2) return s1;
   else return s2;
}

int main()
{
   // testing our variadic sumDiffs with different types and numbers of arguments
   int res1 = sumDiffs(5, 3, 8, 2, 1, -6);
   cout << "(5-3) + (8-2) + (1--6) should be 15, actually got: " << res1 << endl;
   double res2 = sumDiffs(1.0, 2.5, 3.6);
   cout << "(1-2.5) + 3.6 should be 2.1, actually got: " << res2 << endl;

   // testing our higher order apply with different function/parameter combos
   double res3 = apply(sqrt, 0.81);
   cout << "sqrt(0.81) should give 0.9, actually got: " << res3 << endl;
   string str1 = "foo";
   string str2 = "blah";
   string res4 = apply(concat, str1, str2);
   cout << "concat(foo, blah) should give fooblah, actually got: " << res4 << endl;

   // testing our variadic higher order function with different functions and numbers of args
   string res5 = chosenMin(smallStr, str1, str2);
   cout << "smaller of foo and blah should be blah, actually got: " << res5 << endl;
   int res6 = chosenMin(smallInt, 10, 5, 17, -3, 11);
   cout << "smaller of 10, 5, 17, -3, 11 should be -3, actually got: " << res6 << endl;
}

The output we would expect from running this would be something like

(5-3) + (8-2) + (1--6) should be 15, actually got: 15
(1-2.5) + 3.6 should be 2.1, actually got: 2.1
sqrt(0.81) should give 0.9, actually got: 0.9
concat(foo, blah) should give fooblah, actually got: fooblah
smaller of foo and blah should be blah, actually got: blah
smaller of 10, 5, 17, -3, 11 should be -3, actually got: -3