Mastering C++ Templates: A Guide to Creating Your Own Custom Template Library Similar to STL

Mastering C++ Templates: A Guide to Creating Your Own Custom Template Library Similar to STL

ยท

6 min read


๐Ÿ’ก
Have you ever found yourself enviously looking at how effortlessly JavaScript and Python allow you to print arrays and objects during debugging? And also these languages provide various built-in functions, which makes it easy to solve DSA/Competitive Problems problems.

When I was in B.Tech, I used to code in C++ while my friends used Python. In competitive programming contests, my friends would always solve problems quickly using Python's built-in functions and simple syntax. However, I didn't want to switch to Python.

Then, I had an idea. Why not implement my own custom template library to make C++ easier to use and debug? I created a custom template library that included functions like isPrime(), toLowerCase(), gcd(), getPrimeFactors(), isPowerOfTwo(), and printing arrays.

Implementing these functions gave me a much deeper understanding of C++ syntax and built-in functions. After using my custom template library, I was able to solve problems much faster than my friends with less runtime, as C++ is faster than Python

If you're a C++ developer, you might have encountered the frustration of not having a similar convenience at your disposal. But with the power of the C++ templates, we can create our own template library to solve competitive programming questions more easily. We can also implement functions similar to those in other programming languages and print the contents of vectors, maps, pairs, sets, and so on.

We can include some more features in Custom Template Library like:

  1. Print functions for printing Vectors, maps, sets, pairs and array of vectors etc.

  2. We can implement functions that are used very frequently while doing Competitive programming or solving DSA questions.

    For example: isPrime(), toLowerCase(),gcd(),lcm(),getPrimeFactors() etc.

  3. We can make functions using bit manipulation, As these can be very efficient because they work directly with the bits of a number. This can be much faster than using other methods.
    The time complexity of every bitwise operation is O(1). These operations are very very fast.
    For example: isPowerOfTwo(),isEven(),setBit() etc.

  4. We can implement features that are there in Java but not in C++.

  5. We can customize STL functions according to our requirements. And write our function using the overloading concept.

You might ask, Why create a separate template library? Why not just write the code in the same file?๐Ÿค”

There are several advantages to creating a separate template library, including:

  • Code Reusability: A custom template library can be reused in multiple projects, which can save you time and effort.

  • Code Maintainability: Changes or updates to the library can be applied uniformly across multiple projects.

  • Enhanced Debugging and Error Handling: Custom template libraries can include debugging features and error-handling mechanisms that align with your specific needs. This can greatly simplify the debugging process, and provide meaningful error messages.

  • Portability: A custom template library can be more portable than using a general-purpose library because it is not tied to any specific platform or compiler.

  • Developing a custom template library can be a valuable learning experience. It deepens your understanding of C++ templates, generic programming, and advanced language features. It also hones your problem-solving skills and encourages you to think abstractly about software design.

How can we make Custom Template Library?

we can make it by using a collection of .h files(header files). We can define our template classes, functions, or data structures within the header files.

  1. Create a header file.

    One of the most important things while creating a header file is to include header guards. The lines #ifndef PRINT_H and #define PRINT_H are called header guards. They are used to prevent the header file from being included multiple times in the same source file.

    print.h:

#ifndef PRINT_H
#define PRINT_H

#endif
  • #ifndef: Checks to see if the macro PRINT_H has been defined. If it has not been defined, then the code in the header file is included.

  • #define: Defines the macro PRINT_H. This prevents the header file from being included again.

  • #endif: Ends the header guard.

  1. Include a function that overloads operator << and prints std::vector
template <typename T>
std::ostream &operator<<(std::ostream &output, std::vector<T> &v){
      output << "[ ";
      for (auto x : v)
            output << x << " ";
      output << "]";
      return output;
}

Let's take a closer look at the code above and see how it works.

Here we are using the concept of Operator Overloading of << the std::ostream operator. In general, << is used to print normal variables but by overloading this operator we can use it for printing various things like vectors, maps, pairs etc.

  • Template: this is a simple yet very powerful tool in C++. The simple idea is to pass the data type as a parameter so that we donโ€™t need to write the same code for different data types. Above code works for vector<int>, vector<char> etc.

  • The operator<< the function takes two parameters: an ostream object and a vector object. And it returns and ostream object.

  • Inside the function, we will iterate through each element and print it. And also we can keep customized error messages inside the function to debug easily.

You might be wondering why we have to use std:: everywhere. Let me simplify it for you.
->In C++, std is a namespace that stands for the Standard Library. It is a collection of pre-defined classes, functions, and templates provided by the C++ language.

->When we write std::vector, we are referring to the vector of the class provided by the Standard Library. This helps avoid naming conflicts with other classes or libraries that might define their vector class.

->To avoid writing std:: multiple times we can use using namespace std; .When we use this, It imports all names from the std namespace into the current scope. This means you can directly use names such as cout, vector, string, and so on, without the need for the std:: prefix.

  1. Now we can use the above function by including the print.h file in your main file.
#include<iostream>
#include "print.h"
using namespace std;

int main(){
 int a[3]={1,2,3};
 vector<int> v = {1,2,3};
 cout<<v;
    return 0;
}

Output:

[ 1 2 3 ]

"print.h" vs <print.h>: The <print.h> syntax is typically used for header files that are part of the standard library, while the "print.h" syntax is typically used for header files that are created by the programmer.

These are the sample functions that I have implemented in my Custom Template Library.

sample.h :

#ifndef SAMPLE_H
#define SAMPLE_H

// for finding if the number is power of 2 or not
int isPowerof2(int num){
    return (num && !(num & num-1));
} 

// for finding GCD
template<typename T> T 
gcd(T a, T b){
  return(b?__gcd(a,b):a);
}

// For printing pair
template<typename T1,typename T2>
std::ostream & operator<<(std::ostream &out,std::pair<T1,T2> &p){
  out<<"["<<p.first<<","<<p.second<<"]";
   return out;
 }

#endif

For more functions, you can refer to my GitHub repository(C++ Custom Template Library)

Finally...

๐Ÿ’ก
Creating custom template libraries can help you to learn more about the programming language and how it works. This is because you will need to understand the underlying concepts of the language to create efficient and reusable code. Creating custom template libraries can be a valuable addition to your resume. It shows that you have a deep understanding of the programming language and that you can solve complex problems. This can give you an edge over other candidates when applying for jobs.

All The Best๐Ÿ˜

ย