Templates - First Steps

Contents[Show]

The idea of this post is quite simple. I want to visualize templates and, in particular, the process of template instantiation. Thanks to C++ Insights, this visualization is pretty easy.

templates

Templates (class templates or function templates) are families of classes or functions. When you instantiate a template, you create a concrete class or a concrete function out of these families of classes or functions. Here are the first straightforward questions, I want to answer. For simplicity reasons I sometimes call a class template a generic class and a function template a generic function.

When should I use a template?

You should use a template when your function or class stands for such a generic idea, that this idea is not bound to a concrete type. For example, a function such as max or a container such as vector are usable for many types.

How can I create a template?

I assume you have implemented a function max accepting two ints.

int max(int lhs, int rhs) {
    return (lhs > rhs)? lhs : rhs;
}

 Making a template out of the function is in general straightforward.

  1. Put the line template <typename T> before the function
  2. Replace the concrete type int with the type parameter T.
template <typename T>              // (1)
T max(T lhs, T rhs) {              // (2)
    return (lhs > rhs)? lhs : rhs;
}

I have to mark two additional remarks. First, instead of the name typename, you can also use class. I strongly suggest typename, because T must not be a class but can be a  type, a non-type, or a template. Second, by convention, we use T as the name for the first type parameter.

The same procedure also works, when you transform a class into a class template.

Now I come to exactly the point where C++ Insights, provides me with valuable services.

What happens, when I instantiate a template?

Let instantiate the function template max for int and double.

template <typename T>
T max(T lhs, T rhs) {
    return (lhs > rhs)? lhs : rhs;
}

int main() {
  
    max(10, 5);
    max(10.5, 5.5);
  
}

C++ Insights provides a deeper insight into this automatic process of template instantiation:

functionTemplateInstantiation

The process of template instantiation creates lines 6 - 23. Let me write a few words about the instantiation of the function max for the two ints (lines 6 - 13). Line 6 in the screenshot expresses that line 8 in the source file (max(10, 5)) causes the generation of lines 6 - 13. I assume the first two lines of the compiler-generate code are the most interesting ones.

template<>
int max<int>(int lhs, int rhs)
{
  return (lhs > rhs) ? lhs : rhs;
}

max is a fully specialized function template for int: max<int>.  The generic part is empty: template<>. The compiler generates out of the family of max-functions one concrete function for int. Does this also mean that the compiler generates a concrete function for each used type?

What happens, when I instantiated a template more than once for the same type?

My next example is based on class templates. Here is a simple container two times instantiated for int.

template <typename T, int N>
class Array{
 public:
    int getSize() const{
        return N;
    }
 private:
    T elem[N];
};

int main() {
  
    Array<int, 5> myArr1;  // (1)
    Array<int, 10> myArr2; // (2)
    Array<int, 5> myArr3;  // (3)
  
}

I instantiated two times Array<int, 5> (line (1) and (3)) and one time Array<int, 10> (line 2). When you study the output of C++ Insights, you recognize that the second instantiation of Array<int, 5> (line 3) uses the first instantiation already triggered by line (1). Here are the relevant parts of the output.

classTemplateInstantiation

 

Are we done with this example? No! There are two additional interesting observations, I want to make.

First, the process of template instantiation is lazy. Second, I use a non-type template parameter.

Template instantiation is lazy

Did you recognize that the member function getSize() was not instantiated? Only the declaration of the member function is available. The process of template instantiation is lazy. Meaning, if you don't need it will not be instantiated. This works fine so far that you can use invalid code in a member function. Of course, the member function must not be called. If you don't believe me, compile the following small program. First, disable line (1), and second, enable line (1).

// number.cpp

#include <cmath>
#include <string>

template <typename T>
struct Number {
	int absValue() {
        return std::abs(val);
    }
  T val{};
};

int main() {
  
    Number<std::string> numb;
    // numb.absValue();       // (1)
  
}

Let's go back to my previous program and invoke getSize(). Here is the modified main program.

int main() {
  
    Array<int, 5> myArr1;  
    Array<int, 10> myArr2; 
    Array<int, 5> myArr3;  
    myArr3.getSize();     // (1)
  
}

 Accordingly, the following screenshot shows the compiler-generated code for the member function getSize() (lines 18 - 21).

classTemplateGetSize

 

int as a non-type template parameter

I used in this example two type-parameters in the second one is, in particular, an int. int is an example of a non-type template parameter. Besides int, you can use all integral types, floating-point types (C++20), but also pointers, or references as non-type template parameters. What happens, when I instantiated two arrays of different lengths?

template <typename T, int N>
class Array{
 public:
    int getSize() const{
        return N;
    }
 private:
    T elem[N];
};

int main() {
  
    Array<float, 5> myArr1;
    Array<float, 10> myArr2;
  
}

 You probably guessed it. Two arrays are instantiated. Here is the crucial output from C++ Insights

classTemplateTwoInts

This means, that both instantiations using different int values create different types.

What's next

After these first steps with templates, I make in my next post a deep dive into function templates.

 

Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, Marko, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, espkk, Louis St-Amour, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Neil Wang, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Tobi Heideman, Daniel Hufschläger, Red Trip, Alexander Schwarz, Tornike Porchxidze, Alessandro Pezzato, Evangelos Denaxas, Bob Perry, Satish Vangipuram, and Andi Ireland.

 

Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, and Said Mert Turkal.

 

 

My special thanks to Embarcadero CBUIDER STUDIO FINAL ICONS 1024 Small

 

Seminars

I'm happy to give online-seminars or face-to-face seminars world-wide. Please call me if you have any questions.

Bookable (Online)

German

Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

New

Contact Me

Modernes C++,

RainerGrimmSmall

 
 

 

 

Comments   

+1 #1 Kiran 2021-05-05 01:43
Thanks for putting it so clear and detailed way
Eagerly waiting for next post in this series
Quote
0 #2 Pramod Tikare 2021-05-11 11:03
Nice article. I have got 2 feedbacks.
1. It makes sense to add line numbers to your code snippet, since cppinsights displays the line number corresponding to the generic function.

2. In the text, you mention non-type type parameters multiple times. I assume this is a typo error for non-type template parameter.

Thanks!
Quote

My Newest E-Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code

Visitors

Today 980

Yesterday 7645

Week 8625

Month 148832

All 6588913

Currently are 220 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments