Template
Basic Concepts and Syntax
Polymorphism in C++
- Polymorphism: It is the ability to use a single interface to represent different data types or classes. In C++, polymorphism can be achieved through function overloading, operator overloading, and inheritance.
- There are two types of polymorphism: compile-time (static) and runtime (dynamic):
- Compile-time Polymorphism: Also known as static polymorphism, it is resolved during compile time. It is achieved through function overloading, operator overloading, and templates.
- Runtime Polymorphism: Also known as dynamic polymorphism, it is resolved during runtime. It is achieved through inheritance and virtual functions.
- Template: A
template
is a blueprint or formula for creating a generic class or function. It allows the creation of functions and classes that can operate with any data type.
Template Syntax
- Templates begin with the
template
keyword, followed by template parameter lists enclosed in angle brackets (<>
). - Template parameter list: Specifies the types or values that can be used to instantiate the template.
template <typename T, int N>
class MyClass {
// Class implementation
};
Template Body
- The template body is defined using placeholders that are replaced during instantiation with actual arguments.
- The placeholders are specified using the
typename
keyword for types and other keywords likeclass
,int
, etc., for non-type parameters.
template <typename T>
void print(T value) {
std::cout << value << std::endl;
}
The placeholder
T
is replaced by the actual type (likeint
,float
) when the function is called.
Model Polymorphic Behavior Using Templates (Generics)
- Templates in C++ allow you to write generic and reusable code that can handle different data types without duplication. This is known as parametric polymorphism.
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << add(3, 4) << std::endl; // Works with int
std::cout << add(3.5, 2.1) << std::endl; // Works with double
}
The
add
function can work with different data types (int
,double
, etc.) without the need for separate implementations.
Function Templates
Function Template Syntax
- Function templates allow you to define a generic function that can operate with different data types.
- The template parameter list specifies the types or values that can be used to instantiate the function template.
template <typename T>
void swap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
The
swap
function can exchange the values of any two variables of the same type.
Function Template Instantiation
- Function templates are instantiated with actual types or values when called.
- The compiler generates the appropriate function based on the template arguments.
int main() {
int x = 5, y = 10;
swap(x, y); // Instantiates swap<int>(int&, int&)
std::cout << "x: " << x << ", y: " << y << std::endl; // Output: x: 10, y: 5
}
The
swap
function is instantiated withint
as the template argument.
Resolving Ambiguity
- When multiple functions match the template arguments, the compiler may face ambiguity.
- To resolve ambiguity, you can provide explicit template arguments or use function overloading.
template <typename T>
T maximum(T a, T b) {
return a > b ? a : b;
}
int main() {
double a = 3.5, b = 2.1;
float c = maximum<float>(a, b); // Explicit type specification
std::cout << c << std::endl;
}
The
maximum
function is instantiated withfloat
as the template argument. The explicit type specification resolves ambiguity, ensuring the correct type is used in the function call.
Class Templates
Class Template Syntax
- Class templates allow you to define a generic class that can operate with different data types.
- The template parameter list specifies the types or values that can be used to instantiate the class template.
template <typename T>
class Array {
T arr[50];
public:
T& operator[](int i) { return arr[i]; }
};
The
Array
class can store arrays of different types, such asint
,double
, etc.
Class Template Instantiation
- Class templates are instantiated with actual types or values when declared.
- The compiler generates the appropriate class based on the template arguments.
int main() {
Array<int> intArray;
intArray[0] = 10;
std::cout << intArray[0] << std::endl; // Output: 10
Array<double> doubleArray;
doubleArray[0] = 3.14;
std::cout << doubleArray[0] << std::endl; // Output: 3.14
}
The
Array
class is instantiated withint
anddouble
as the template arguments.
Static Data Member Declarations in a Class Template
- Class templates can have static data members, which are shared among all instances of the template.
- Static data members in a class template must be explicitly declared and defined outside the class template.
- The declaration specifies the template parameter list for the static data member.
template <typename T = int, int SIZE = 50>
class Array {
T arr[SIZE];
static unsigned count;
public:
Array() { ++count; }
~Array() { --count; }
static unsigned getCount() { return count; }
};
template <typename T, int SIZE>
unsigned Array<T, SIZE>::count = 0;
The
Array
class template has a static data membercount
that tracks the number of instances created.
Template Specialization and Overloading
Template Specialization
- Template specialization allows you to define specific behavior for a particular data type, overriding the generic template.
template <typename T>
T maximum(T a, T b) {
return a > b ? a : b;
}
template <>
const char* maximum<const char*>(const char* a, const char* b) {
return strcmp(a, b) > 0 ? a : b;
}
The
maximum
function is specialized forconst char*
data type to compare C-style strings usingstrcmp
.
Template Overloading
- Template overloading allows you to define multiple template functions with the same name but different template parameter lists.
- Overloading vs Specialization: Overloading provides different function implementations based on the argument types, while specialization provides a specific implementation for a particular type within a template.
template <typename T>
T maximum(T a, T b) {
return a > b ? a : b;
}
const char* maximum(const char* a, const char* b) {
return strcmp(a, b) > 0 ? a : b;
}
The second
maximum
function overloads the template forconst char*
without using specialization, showcasing flexibility.
Advanced Template Features
Default Template Parameter Values
- Templates can have default parameter values, making them more flexible and easier to use without specifying every detail.
template <typename T = int, int SIZE = 50>
class Array {
T arr[SIZE];
public:
T& operator[](int i) { return arr[i]; }
};
This allows the
Array
class to be instantiated without providing explicit template arguments.