Template in C++ - from first tries toward generic programming to variadics
adib 11/22/2020
One of the first works done to be generic in programming was implementing the number of overloads that we want for that function template. Although in this way of doing generics, we couldn't reach complete templates.
Also overloading functions itself is very useful nowadays, but that time for the solving generic programming problems it came to the scene. Now take a look at getting generic by using overloads:
// function template for integers int func(int a, int b) { return a + b; } // function template for doubles double func(double a, double b) { return a + b; } // function template for strings // if applicable, and just to be an example of templates string func(string a, string b) { return a + b; } int main() { // here when we pass some integer to func(), // the integer version would be called func(1, 3); // double(float) version func(6.5, 4.2); // string version func("A", "B"); }
Simple function template
Also there are class templates, but they are much like function templates. Normal template functions in C++:
// Basic function template template <typename T> T func(T a, T b) { return a + b; } int main() { // here when we pass some integer to func(), // T will be replaced with integer func(1, 3); // double(float) version func(6.5, 4.2); // string version func("A", "B"); }
Variadic Templates
As the name suggests, the name variadic is come from varying.
And the idea of variadic templates can come from problems like being stuck in situations like resource management issues or memory leak problems when you define overloads and you forget to free the memory for the program.
Variadic template also has made function overloading much easier. By having one template you can request the function overloads you want, and the template executes it in the right way for you. Here I explained how Variadic Template is defined:
// Base version template <typename U> void printspecs(const U& u) { cout << "properties of the car entered : " << u << endl; } // A car show spec method template <typename Model, typename... Props> void printspecs(const Model& model, const Props&... prop) { // car model cout << "properties of the car entered : " << model << endl; // other properties of that car printspecs(prop...); } int main() { // Done, using string streams int year = 2019; string model = "750li"; ostringstream oss; oss << model << year; cout << oss.str(); // Done using variadic template printspecs(750, "New", 2019); }
Change extension Pack Behaviour
Declaring how many args expansion pack is, is on your decision. you can force as many arguments as you want to execute the function in the best way
template <typename First, typename Second, typename... Rest> void calc(const First& first, const Second& second, const Rest&... rest) template <typename One, typename Two, typename Three, typename... Rest> void calc(const One& one, const Two& two, const Three& three, const Rest&... rest)