# Template in C++

## General Purpose Functions:

General purpose functions are functions that can be used for a variety of purposes, rather than being specific to a particular task or data type. They are typically designed to be reusable and flexible, and can be used in a wide range of applications.

Example:

```cpp
#include <iostream>

template <typename T>
void swap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 1, y = 2;
    std::cout << "Before swap: x = " << x << ", y = " << y << std::endl;
    swap(x, y);
    std::cout << "After swap: x = " << x << ", y = " << y << std::endl;
    return 0;
}
```

In this example, we define a general purpose function called `swap` that can be used to swap the values of two variables of any type. The function takes two references to a template parameter `T`, which can be any type, and swaps their values using a temporary variable. We then use this function to swap the values of two `int` variables in the `main` function.

## Macros:

Macros are preprocessor directives that are used to define constants, functions, or other constructs that can be used throughout a program. They are typically defined using the `#define` directive, and can contain parameters that are replaced with their values at compile time.

Example:

```cpp
#include <iostream>

#define PI 3.14159

int main() {
    double radius = 5.0;
    double area = PI * radius * radius;
    std::cout << "Radius: " << radius << ", Area: " << area << std::endl;
    return 0;
}
```

In this example, we define a macro called `PI` that represents the value of pi, and use it to calculate the area of a circle with a given radius. The macro is defined using the `#define` directive, and is used in a mathematical expression in the `main` function.

## Function Templates:

Function templates are functions that can be used to define a family of functions that operate on different types or values. They are defined using the `template` keyword followed by a template parameter list, which specifies one or more template parameters that can be used to define the types or values that the function operates on.

Example:

```cpp
#include <iostream>

template <typename T>
T max(T a, T b) {
    return a > b ? a : b;
}

int main() {
    int x = 1, y = 2;
    double a = 3.14, b = 2.71;
    std::cout << "Max of " << x << " and " << y << " is " << max(x, y) << std::endl;
    std::cout << "Max of " << a << " and " << b << " is " << max(a, b) << std::endl;
    return 0;
}
```

In this example, we define a function template called `max` that can be used to find the maximum of two values of any type. The function takes two parameters of type `T`, which is a template parameter that can be any type. We then use this function template to find the maximum of two `int` variables and two `double` variables in the `main` function.

## Template Parameters:

Template parameters are parameters that are used to define the types or values that a function or class template operates on. They are specified in a template parameter list within angle brackets (`<>`), and can be of several different types, including type parameters, non-type parameters, and template parameters.

Example:

```cpp
template <typename T, int N>
class Array {
public:
    Array() : data(new T[N]) {}
    ~Array() { delete[] data; }
private:
    T* data;
};
```

In this example, we define a class template called `Array` that represents a fixed-size array of elements of type `T`. The template has two template parameters: `T`, which is a type parameter that specifies the type of the elements in the array, and `N`, which is a non-type parameter that specifies the size of the array. The `Array` class uses these template parameters to allocate and deallocate the memory for the array.

## Template Parameter Conversion:

Template parameter conversion is the process of converting a template parameter to a different type or value. This is typically done using a type or value conversion operator, which is a function that is defined in the template class or function and is used to convert the template parameter to the desired type or value.

Example:

```cpp
template <typename T>
class MyClass {
public:
    operator int() const { return static_cast<int>(value); }
private:
    T value;
};

int main() {
MyClass<double> obj(3.14);
    int i = obj;
    std::cout << "i = " << i << std::endl;
    return 0;
}
```

In this example, we define a class template called `MyClass` that has a single template parameter `T`. The class has a conversion operator that converts an object of type `MyClass<T>` to an `int` by casting its `value` member to an `int`. We then create an object of type `MyClass<double>` with a value of `3.14`, and use the conversion operator to convert it to an `int` in the `main` function.

## Function Template Problem:

One problem that can occur with function templates is that the compiler may not be able to deduce the correct template parameter types from the function arguments. This can result in a compilation error, as the compiler is unable to instantiate the function template with the correct types.

Example:

```cpp
#include <iostream>

template <typename T>
void print(T value) {
    std::cout << value << std::endl;
}

int main() {
    print(42);
    return 0;
}
```

In this example, we define a function template called `print` that takes a single parameter of type `T` and prints it to the console. We then call the `print` function with an `int` value in the `main` function. However, the compiler is unable to deduce the template parameter type from the argument, as there is no explicit type specified for the argument. This results in a compilation error.

To fix this problem, we can either specify the template parameter type explicitly (`print<int>(42)`), or provide additional overload functions that accept specific types (`void print(int value)`).

## Generic Programming:

Generic programming is a programming paradigm that emphasizes the use of generic algorithms and data structures that can be used with a variety of types and values. It is based on the idea of abstraction and code reuse, and is often used in libraries and frameworks that are designed to be used in a wide range of applications.

Example:

```cpp
#include <iostream>
#include <algorithm>
#include <vector>

template <typename T>
void print(const std::vector<T>& vec) {
    std::cout << "[ ";
    for (const auto& item : vec) {
        std::cout << item << " ";
    }
    std::cout << "]" << std::endl;
}

int main() {
    std::vector<int> vec1 = {1, 2, 3};
    std::vector<double> vec2 = {2.71, 3.14, 4.13};
    std::sort(vec1.begin(), vec1.end());
    std::sort(vec2.begin(), vec2.end());
    print(vec1);
    print(vec2);
    return 0;
}
```

In this example, we define a function template called `print` that takes a `std::vector` of any type and prints its contents to the console. We then use this function template to print the contents of two different vectors of `int` and `double` values in the `main` function, and sort them using the `std::sort` algorithm from the standard library.

## General Purpose Classes:

General purpose classes are classes that can be used for a variety of purposes, rather than being specific to a particular task or data type. They are typically designed to be reusable and flexible, and can be used in a wide range of applications.

Example:

```cpp
template <typename T>
class Stack {
public:
    Stack() : top(0), max_size(100) { data = new T[max_size]; }
    ~Stack() { delete[] data; }
    void push(const T& item) { data[top++] = item; }
    T pop() { return data[--top]; }
    bool empty() const { return top == 0; }
private:
    T* data;
    size_t top;
    size_t max_size;
};
```

In this example, we define a class template called `Stack` that represents a stack of elements of type `T`. The template has a single template parameter `T`, which specifies the type of the elements in the stack. The `Stack` class provides several member functions for manipulating the stack, including `push`, `pop`, and `empty`.

## Class Templates:

Class templates are used to create a family of classes that share a common structure or behavior but operate on different types or values. The class template itself is not a class, but a blueprint for creating classes. The actual class is created by instantiating the template with specific types or values.

Example:

```cpp
template <typename T>
class Array {
public:
    Array(size_t size) : data(new T[size]), size(size) {}
    ~Array() { delete[] data; }
    T& operator[](size_t index) { return data[index]; }
    const T& operator[](size_t index) const { return data[index]; }
private:
    T* data;
    size_t size;
};
```

In this example, we define a class template called `Array` that represents a fixed-size array of elements of type `T`. The template has a single template parameter `T`, which specifies the type of the elements in the array. The `Array` class provides several member functions for accessing and manipulating the elements of the array.

## Array Class Implementation (array.h):

The `Array` class implementation is a concrete example of a class template instantiation. It is created by instantiating the `Array` class template with a specific type or value.

Example:

```cpp
#include "array.h"

int main() {
    Array<int> arr(5);
    for (size_t i = 0; i < arr.size(); i++) {
        arr[i] = i;
    }
    for (size_t i = 0; i < arr.size(); i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
    return 0;
}
```

In this example, we instantiate the `Array` class template with the `int` type to create an array of integers with a size of 5. We then use a loop to set the values of the array to their indices, and another loop to print the values to the console.

## Using the Array Template:

To use the `Array` class template, we must first include the template definition in our code. We can then instantiate the template with a specific type or value to create a concrete class.

Example:

```cpp
#include "array.h"

int main() {
    Array<int> arr(5);
    for (size_t i = 0; i < arr.size(); i++) {
        arr[i] = i;
    }
    for (size_t i = 0; i < arr.size(); i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
    return 0;
}
```

In this example, we include the `array.h` header file, which defines the `Array` class template. We then instantiate the template with the `int` type to create an array of integers with a size of 5. We use a loop to set the values of the array to their indices, and another loop to print the values to the console.

## Template Parameters:

Template parameters are used to define the types or values that a class or function template operates on. They are specified in a template parameter list within angle brackets (`<>`), and can be of several different types, including type parameters, non-type parameters, and template parameters.

Example:

```cpp
template <typename T, int N>
class Array {
public:
    Array() : data(new T[N]) {}
    ~Array() { delete[] data; }
private:
    T* data;
};
```

In this example, we define a class template called `Array` that represents a fixed-size array of elements of type `T`. The template has two template parameters: `T`, which is a type parameter that specifies the type of the elements in the array, and `N`, which is a non-type parameter that specifies the size of the array. The `Array` class uses these template parameters to allocate and deallocate the memory for the array.

## Class Template Instantiation:

Class template instantiation is the process of creating a concrete class from a class template by replacing the template parameters with specific types or values.

Example:

```cpp
template <typename T>
class MyClass {
public:
    void print() { std::cout << "Type: " << typeid(T).name() << std::endl; }
};

int main() {
    MyClass<int> obj1;
    MyClass<double> obj2;
    obj1.print();
    obj2.print();
    return 0;
}
```

In this example, we define a class template called `MyClass` that has a single template parameter `T`. The class has a member function called `print` that prints the type of the template parameter to the console using the `typeid` operator. We then instantiate the `MyClass` template with the `int` and `double` types to create two concrete classes, and call the `print` function on each object.

## Non-Type ParameterConversion:

Non-type template parameters are values that are passed to a template as a parameter, but are not of a type. They can be of several different types, including integral types, enumerations, pointers, and references. Non-type parameters can be converted to other types using type conversion operators.

Example:

```cpp
template <int N>
class MyClass {
public:
    void print() { std::cout << "Value: " << N << std::endl; }
};

int main() {
    MyClass<5> obj1;
    MyClass<3 + 2> obj2;
    obj1.print();
    obj2.print();
    return 0;
}
```

In this example, we define a class template called `MyClass` that has a single non-type template parameter `N`. The class has a member function called `print` that prints the value of the non-type parameter to the console. We then instantiate the `MyClass` template with the values `5` and `3 + 2` to create two concrete classes, and call the `print` function on each object.

## Standard Template Library (STL):

The Standard Template Library (STL) is a collection of classes and functions that are part of the C++ standard library. It provides a set of generic programming tools that can be used to solve a wide range of programming problems. The STL is based on the principles of generic programming, which emphasizes the use of templates and algorithms that can operate on a wide range of data types and structures.

Example:

```cpp
#include <vector>
#include <algorithm>
#include <iostream>

int main() {
    std::vector<int> v{ 1, 2, 3, 4, 5 };
    std::reverse(v.begin(), v.end());
    for (auto x : v) {
        std::cout << x << " ";
    }
    std::cout << std::endl;
    return 0;
}
```

In this example, we use several components of the STL to reverse the elements of a vector of integers and print them to the console. We include the `<vector>` and `<algorithm>` headers, which provide the necessary classes and functions. We create a vector `v` with the values `1, 2, 3, 4, 5`, and use the `std::reverse` algorithm to reverse the order of the elements in the vector. We then use a range-based for loop to print the elements of the vector to the console.

## STL Components:

The STL is composed of several different components, including containers, iterators, algorithms, and function objects.

* Containers: Containers are objects that store collections of elements. Examples include vectors, lists, maps, and sets.
* Iterators: Iterators are objects that provide a way to access the elements of a container. They can be used to traverse the elements of a container and perform operations on them.
* Algorithms: Algorithms are functions that operate on containers and their elements. They can be used to perform a wide range of operations, including sorting, searching, and transforming.
* Function objects: Function objects are objects that behave like functions. They can be used as arguments to algorithms to customize their behavior.

## Generic Programming:

Generic programming is a programming paradigm that emphasizes the use of templates and algorithms that can operate on a wide range of data types and structures. It is based on the idea of writing code that is independent of specific data types, but can be instantiated with specific types at compile time. This allows for the creation of reusable code that can be applied to a wide range of programming problems.

Example:

```cpp
template <typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    int x = 3, y = 5;
    double a = 1.5, b = 2.5;
    std::cout << max(x, y) << std::endl;
    std::cout << max(a, b) << std::endl;
    return 0;
}
```

In this example, we define a function template called `max` that returns the maximum of two values of the same type. The function takes two template parameters `T` and `U`, which represent the types of the values. We use the ternary operator `? :` to return the larger of the two values. We then instantiate the `max` template with the types `int` and `double` to create two concrete functions, and call them with different values.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://adeshsingh.gitbook.io/programming/advanced-c++-programming/template-in-c++.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
