Why Template?
#include <iostream> class comprehendTemplate { private: int val; public: comprehendTemplate(int num) : val(num) { std::cout << "val " << val; } }; int main() { comprehendTemplate ct(9); comprehendTemplate ct2("Hello"); return 0; }
<source>: In function 'int main()':
<source>:15:28: error: invalid conversion from 'const char*' to 'int' [-fpermissive]
15 | comprehendTemplate ct2("Hello");
| ^~~~~~~
| |
| const char*
<source>:7:32: note: initializing argument 1 of 'comprehendTemplate::comprehendTemplate(int)'
7 | comprehendTemplate(int num) : val(num) {
| ~~~~^~~
ASM generation compiler returned: 1
<source>: In function 'int main()':
<source>:15:28: error: invalid conversion from 'const char*' to 'int' [-fpermissive]
15 | comprehendTemplate ct2("Hello");
| ^~~~~~~
| |
| const char*
<source>:7:32: note: initializing argument 1 of 'comprehendTemplate::comprehendTemplate(int)'
7 | comprehendTemplate(int num) : val(num) {
| ~~~~^~~
Execution build compiler returned: 1 |
Click here to debug the above program.
Template
Function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type.
template <typename identifier> function_declaration;
template <class identifier> function_declaration;
Both have the same meaning and are indistinct.
A variable template is therefore a template that defines a series of variables, based on one or more template parameters: (C++14 feature)
template<typename T>
T variable_name{};
Now let's try to create general programming paradigm.
Template for class
#include <iostream>
template <class T>
class comprehendTemplate {
private:
T val;
public:
comprehendTemplate(T num) : val(num) {
std::cout << "val " << val;
}
};
int main()
{
comprehendTemplate ct(9);
comprehendTemplate ct2("Hello");
return 0;
} |
In function 'int main()':
Line 15: error: missing template arguments before 'ct'
compilation terminated due to -Wfatal-errors. |
In this case, we have used T as the template parameter name it is shorter and in fact is a very common template parameter name. But you can use any identifier you like.
The above class comprehendTemplate is template class, so to create object for this we need to use the following format.
class-name <type>object-name(<parameters if any>);
Still our C++ compilers are not intelligent to detect the type automatically.
Template for constructors
#include <iostream> template <class T> class comprehendTemplate { private: T val; public: comprehendTemplate(T num) : val(num) { std::cout << "val " << val << std::endl; } }; int main() { comprehendTemplate <int>ct(9); comprehendTemplate <std::string>ct2("Hello"); return 0; }
When the compiler encounters this call to a template function, it uses the template to automatically generate a function replacing each appearance of 'T' by the type passed as the actual template parameter (int in this case) and then calls it. This process is automatically performed by the compiler and is invisible to the programmer.
Template for Member functions
#include <iostream>
template <class T>
class comprehendTemplate {
private:
T val;
public:
comprehendTemplate(T num) : val(num) {
std::cout << "val " << val << std::endl;
}
T getVal() { return val; };
};
int main()
{
comprehendTemplate <int>ct(9);
comprehendTemplate <std::string>ct2("Hello");
std::cout << "getVal of ct " << ct.getVal() << std::endl;
std::cout << "getVal of ct2 " << ct2.getVal() << std::endl;
return 0;
}
Template for Member function & constructor defined outside class
#include <iostream>
template <class T>
class comprehendTemplate {
private:
T val;
public:
comprehendTemplate(T num);
T getVal();
};
comprehendTemplate::comprehendTemplate(T num) :
val(num) {
std::cout << "val " << val << std::endl;
}
T comprehendTemplate::getVal()
{
return val;
}
int main()
{
comprehendTemplate <int>ct(9);
comprehendTemplate <std::string>ct2("Hello");
std::cout << "getVal of ct " << ct.getVal() << std::endl;
std::cout << "getVal of ct2 " << ct2.getVal() << std::endl;
return 0;
} |
#include <iostream> template <class T> class comprehendTemplate { private: T val; public: comprehendTemplate(T num); T getVal(); }; template <class T> comprehendTemplate<T>::comprehendTemplate(T num) : val(num) { std::cout << "val " << val << std::endl; } template <class T> T comprehendTemplate<T>::getVal() { return val; } int main() { comprehendTemplate <int>ct(9); comprehendTemplate <std::string>ct2("Hello"); std::cout << "getVal of ct " << ct.getVal() << std::endl; std::cout << "getVal of ct2 " << ct2.getVal() << std::endl; return 0; }
Template for Copy Constructor & Assignment Operator
#include <iostream> template <class T> class comprehendTemplate { private: T val; public: comprehendTemplate(T num):val(num) { std::cout << "Parameterised Constructor" << std::endl; std::cout << "val " << val << std::endl; } comprehendTemplate(const comprehendTemplate& other) { std::cout << "Copy Constructor" << std::endl; val = other.val; } comprehendTemplate& operator=(const comprehendTemplate& other) { if (this != &other) { std::cout << "Assignment Operator Constructor" << std::endl; val = other.val; } return *this; } T getVal(){ return val; } }; int main() { comprehendTemplate <int>ct(9); comprehendTemplate <std::string>ct2("Hello"); std::cout << "getVal of ct " << ct.getVal() << std::endl; std::cout << "getVal of ct2 " << ct2.getVal() << std::endl; comprehendTemplate <std::string>ct3 = ct2; std::cout << "ct3 is a copy of ct2 " << ct3.getVal() << std::endl; comprehendTemplate <int>ct4(10); std::cout << "getVal of ct4 " << ct4.getVal() << std::endl; ct4 = ct; std::cout << "ct4 replaces the data with ct " << ct4.getVal() << std::endl; return 0; }
Template for pointer member variables
#include <iostream> class comprehendTemplate { private: int* val; public: comprehendTemplate(int num) : val(new int(num)) { std::cout << "val " << val << std::endl; } int getVal() { int num = *val; return num; }; }; int main() { comprehendTemplate ct(9); std::cout << "getVal of ct " << ct.getVal() << std::endl; return 0; }
#include <iostream> template <class T> class comprehendTemplate { private: T* val; public: comprehendTemplate(T* num):val(new T) { std::cout << "Parameterised Constructor" << std::endl; val = num; std::cout << "val " << *val << std::endl; } comprehendTemplate(const comprehendTemplate& other) { std::cout << "Copy Constructor" << std::endl; val = other.val; } comprehendTemplate& operator=(const comprehendTemplate& other) { if (this != &other) { std::cout << "Assignment Operator Constructor" << std::endl; val = other.val; } return *this; } T* getVal(){ return val; } }; int main() { int var = 9; comprehendTemplate <int>ct(&var); //comprehendTemplate <std::string>ct2("Hello"); std::cout << "getVal of ct " << ct.getVal() << " " << *(ct.getVal()) << std::endl; //std::cout << "getVal of ct2 " << ct2.getVal() << std::endl; comprehendTemplate <int>ct3 = ct; std::cout << "ct3 is a copy of ct " << ct3.getVal() << std::endl; //var = 10; int var2 = 10; comprehendTemplate <int>ct4(&var2); std::cout << "getVal of ct4 " << ct4.getVal() << " " << *(ct4.getVal()) << std::endl; ct4 = ct; std::cout << "ct4 replaces the data with ct " << ct4.getVal() << std::endl; return 0; }
Template for Arrays
Template for two classes
Template for free functions
#include <iostream> using namespace std; // One function works for all data types. // This would work even for user defined types // if operator '>' is overloaded template <typename T> T myMax(T x, T y) { return (x > y) ? x : y; } int main() { // Call myMax for int cout << myMax<int>(3, 7) << endl; // call myMax for double cout << myMax<double>(3.0, 7.0) << endl; // call myMax for char cout << myMax<char>('g', 'e') << endl; return 0; }
Generics
Generics can be implemented using C++ templates.
Advantages
Template generally deduces the size from the variable passed which is called template parameter deduction.
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.
References
Class with classname given as a template argument
Comments
Post a Comment