Generic
Programming
Generic Programming
• Generic programming in C++ is a paradigm that allows you to write
code in a way that is abstracted from any specific type. This allows for
the creation of flexible and reusable components. The primary
mechanism for generic programming in C++ is through the use of
templates.
Generic Programming
• The method of Generic Programming is implemented to increase
the efficiency of the code. Generic Programming enables the
programmer to write a general algorithm which will work with
all data types. It eliminates the need to create different
algorithms if the data type is an integer, string or a character.
The advantages of Generic
Programming are
1.Code Reusability
2.Avoid Function Overloading
3.Once written it can be used for multiple times and
cases.
Templates in C++
• Templates is simple yet very powerful tool in C++.
• Templates are the foundation of generic programming, which involves writing code in
a way that is independent of any particular type.
• A template is a blueprint or formula for creating generic function or class`.
Two Types of Templates are:
a) Function Template
b) Class Template
Function Overloading
int add(int x,int y)
{
return(x+y);
}
double add(double x,double y)
{
return(x+y);
}
int main()
{
cout<<add(2,3)<<endl;
cout<<add(5.6,3.3);
}
Function Overloading
int great(int x,int y)
{
return(x>y?x:y);
}
float great(double x,double y)
{
return(x>y?x:y);
}
int main()
{
cout<<great(2,3)<<endl;
cout<<great(5.6,3.3);
}
Syntax to declare Template
template <class identifier> function_declaration;
// or
template <typename identifier> function_declaration;
• Either we use the class keyword or typename. Both
approaches are the same.
Template
template <class T>
T num(T a, T b)
{
return (a > b ? a : b);
}
int main()
{
int x = 5, y = 2;
float a = 4.5, b = 1.3;
cout << num(x, y) << "\n";
cout << num(a, b);
}
Macros vs Templates
Macros and templates are both mechanisms in C++ for achieving generic
Macros
programming. Templates
Macros operate purely on text and offer no type safety Templates provide strong type safety because they are type-
guarantees. aware and checked by the compiler.
Macros, being text substitutions, can obscure debugging and Templates produce more readable and maintainable code
make code harder to understand. because they are part of the C++ language syntax and benefit
from compiler error messages.
Macros are global and can potentially pollute the global Templates respect C++ scoping rules and can be confined
namespace. within namespaces and classes, enhancing encapsulation and
reducing name clashes.
Macros are typically used for simple text substitutions or Templates are suitable for most generic programming needs
when compatibility with older codebases or languages (like C) in modern C++, providing better safety and flexibility.
is necessary.
Macros vs Templates
#define Square(x) ((x) * (x)) template <typename T>
T Square(T x)
int main() {
{ return x * x;
int a = 5; }
int result = Square(a++); // int main()
Expands to: ((a++) * (a++)), leads to {
undefined behavior int a = 5;
} int result = Square(a); // Calls
Square<int>(5)
}
Macros vs Templates
#define Max(x,y) (x>y?x:y)
int main()
{
int a=3,b=7;
cout<<Max(a,b)<<endl;
cout<<Max(a++,b++)<<endl;
cout<<Max(a,b);
}
Macros vs Templates
template <typename T>
T Max(T x,T y)
{
return(x>y?x:y);
}
int main()
{
int a=3,b=7;
cout<<Max(a,b)<<endl;
cout<<Max(a++,b++)<<endl;
cout<<Max(a,b);
}
Function with two generic types
template<typename T1, typename T2>
void print(T1 first, T2 second)
{
cout<<first<<" "<<second;
}
int main()
{
print(42, "Hello, World!");
print(3.14, 42);
print("Template", 123.456);
}
Explicitly overloading a generic function
// Generic template function
template<typename T>
int main() {
T print(T x)
print(42); // Calls the int specialization
{ cout << endl;
cout << x; print(3.14); // Calls the generic template
} cout << endl;
print("Hello, world!"); // Calls the generic template
// Explicit specialization for int cout << endl;
template<> print(std::string("Hello")); // Calls the generic
int print(int x) template
cout << endl;
{
cout << " (integer)"; return 0;
cout << x; }
}
Explicitly overloading a generic function
template <class T>
void display(T t1)
{ int main()
cout << "Displaying Template: "
<< t1 << "\n"; {
} display(200);
template<> display(12.40);
int display(int t1)
{
display('G'); return 0;
cout << "Explicitly display: " }
<< t1 << "\n";
}
Explicitly overloading a generic function
#include <iostream>
// Generic function
template <typename T>
void print(T value)
{ int main()
cout << value << endl;
} {
template<>
void print(int value)
print(42);
{ print(3.14);
cout << "Integer: " << value << endl;
} print("Hello");
template<> }
void print(double value)
{
cout << "Double: " << value << endl;
}
Using standard parameters with template functions
template<typename T>
T fun(T r, double pi=3.14) int main()
{ {
double area=pi*r*r; fun(4,5);
cout<<"Area of circle is fun(10);
"<<area; }
}
Using standard parameters with template functions
template <typename T>
T power(T base, int exponent = 2)
int main()
{
{
T result = 1;
cout << "Power of 5 with exponent 3: " <<
for (int i = 0; i < exponent; ++i)
power(5, 3) << endl;
{
cout << "Power of 3.5 with default exponent (2): "
result = result*base;
<< power(3.5) <<endl;
}
}
return result;
}
Using standard parameters with template functions
template<class X>
void tab(X data, int tab=1)
{
int main()
for(; tab; tab--) {
for(int i=0; i<8; i++) tabo("This is a test");
{ tabo(100, 1);
cout << ' ‘; tabo('X', 2);
} tabo(10/3, 3);
cout << data << "\n";
}
}
Generic function restrictions in C++
1. Not all operations are generic:
• Generic functions work well for operations that are
independent of specific data types. For example, finding the
maximum of two values can be done for integers, doubles, or
even custom types with a proper > operator overload.
• However, operations that rely on specific properties of a data
type might not be suitable for generics. For instance, you
cannot write a generic function to convert an integer to a
string because the conversion logic depends on the specific
string representation used.
Generic function restrictions in C++
2. No virtual functions in templates:
Template functions cannot have virtual functions. Virtual functions are used for
polymorphism, which relies on runtime type information. Since templates are
resolved at compile time, virtual functions wouldn't work in this context.
Generic function restrictions in C++
3. Limited friend functions with templates:
Friend functions can be declared with templates, but they lose the ability to
access private members of the templated class. This is to prevent unintended
access and maintain encapsulation.
4. Performance considerations:
While generics offer code reuse, in some cases, compiling a generic function for
different types might lead to slightly less efficient code compared to a
specifically written function. This is because the compiler might need to
generate multiple versions of the function for different types.