Download as pdf or txt
Download as pdf or txt
You are on page 1of 441

3/20/22, 5:28 PM Function Templates - Generic Programming Templates in C++

(/learn)

Function Templates
In this lesson, we'll explore function templates in detail.

We'll cover the following

• Function Templates

• Passing Arguments in Function Templates


• Instantiation

• Overloading

Function Templates#
A function template will be defined by placing the keyword template
followed by type or non-type parameters in front of a concrete
function.
After that, you replace the concrete types or non-types with the type or non-
type parameters in the function.

The keyword class or typename declares the parameters.


The name T is usually used for the first parameter.
The parameters can be used in the body of the function.

Passing Arguments in Function Templates#


In the given code snippet, we’ll look at how we can call the initialized
variables with our template. Look at line 2, the function arguments x and y
in the function xchg must have the same type. By providing two type
parameters like in line 5, the types of arguments can be different. In line 9,
https://www.educative.io/courses/generic-templates-in-cpp/mEK9vPWE2qn 1/4
3/20/22, 5:28 PM Function Templates - Generic Programming Templates in C++
parameters like in line 5, the types of arguments can be different. In line 9,
you see a non-type template parameter N .

1 template <typename T>
2 void xchg(T& x , T& y){
3 ...
4
5 template <typename T, typename T1>
6 void  add(T& x, T1& y){
7 ...
8
9 template <int N>
10 int nTimes(int n){
11 ...

Instantiation#
The process of substituting the template parameters for the template
arguments is called template instantiation.

The compiler:

Automatically creates an instance of the function template.


Will automatically create a function template if the template
parameters can be derived from the function arguments.

If the compiler cannot deduce the template arguments from the function
arguments, you will have to specify them explicitly.

1 template <typename T>
2 void xchg(T& x, T& y){ ...
3
4 int a, b;
5 xchg(a, b);
6
7 template <int N>
8 int nTimes(int n){ ...
9
10 int n = 5;
11 nTimes<10>(n);

https://www.educative.io/courses/generic-templates-in-cpp/mEK9vPWE2qn 2/4
3/20/22, 5:28 PM Function Templates - Generic Programming Templates in C++

Overloading#
Function templates can be overloaded.

The following rules hold:

1. Templates do not support an automatic type conversion.

2. If a free function is better or equally as good as a function template that


already exists, the free function can be used.
3. You can explicitly specify the type of the function template.

    func<type>(...)

4. You can specify that you are only interested in a specific instantiation of
a function template.

    func<>(...)

To learn more about function templates, click here


(https://en.cppreference.com/w/cpp/language/function_template).

In the next lesson, we’ll look at the examples of function templates.

Back Next

Who Should Take this Course? - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/mEK9vPWE2qn 3/4
3/20/22, 5:28 PM Function Templates - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/mEK9vPWE2qn 4/4
3/20/22, 7:02 PM - Examples - Generic Programming Templates in C++

- Examples
Let's take a look at the examples of function templates in this lesson.

We'll cover the following

• Example 1: Templates in Functions

• Explanation
• Example 2: Overloading Function Templates

• Explanation

Example 1: Templates in Functions#


1 // templateFunctionsTemplates.cpp
2
3 #include <iostream>
4 #include <string>
5 #include <vector>
6
7 template <typename T>
8 void xchg(T& x, T& y){
9   T t = x;
10   x =y;
11   y =t;
12 }
13
14 template <int N>
15 int nTimes(int n){
16   return N * n;
17 }
18
19 int main(){
20
21   std::cout << std::endl;
22
23 bool t true;
https://www.educative.io/courses/generic-templates-in-cpp/qZ1WEvv4nXD 1/6
3/20/22, 7:02 PM - Examples - Generic Programming Templates in C++
23   bool t = true;
24   bool f = false;
25   std::cout << "(t, f):  (" << t << ", " << f << ") "<< std::endl;
26   xchg(t, f);
27   std::cout << "(t, f):  (" << t << ", " << f << ") "<< std::endl;
28
29   std::cout << std::endl;
30
31   int int2011 = 2011;
32   int int2014 = 2014;
33   std::cout << "(int2011, int2014):  (" << int2011 << ", " << int2014 << ") "<< std:
34   xchg(int2011, int2014);
35   std::cout << "(int2011, int2014):  (" << int2011 << ", " << int2014 << ") "<< std:
36
37   std::cout << std::endl;
38
39   std::string first{"first"};
40   std::string second{"second"};
41   std::cout << "(first, second):  (" << first << ", " << second << ") "<< std::endl;
42   xchg(first, second);
43   std::cout << "(first, second):  (" << first << ", " << second << ") "<< std::endl;
44
45   std::cout << std::endl;
46   std::vector<int> intVec1{1, 2, 3, 4, 5};
47   std::vector<int> intVec2{5, 4, 3, 2, 1};
48
49   std::cout << "vec1: ";
50   for (auto v: intVec1)std::cout  << v << " ";
51   std::cout << "\nvec2: ";
52   for (auto v: intVec2)std::cout << v << " ";
53   std::cout << std::endl;
54   xchg(intVec1, intVec2);
55
56   std::cout << "vec1: ";
57   for (auto v: intVec1)std::cout  << v << " ";
58   std::cout << "\nvec2: ";
59   for (auto v: intVec2)std::cout << v << " ";
60   std::cout << std::endl;
61
62
63   std::cout << "\n\n";
64
65   std::cout << "nTimes<5>(10): " << nTimes<5>(10) << std::endl;
66   std::cout << "nTimes<10>(5): " << nTimes<10>(5) << std::endl;
67
68   std::cout << std::endl;
69 }

https://www.educative.io/courses/generic-templates-in-cpp/qZ1WEvv4nXD 2/6
3/20/22, 7:02 PM - Examples - Generic Programming Templates in C++

Output 1.4s

(t, f): (1, 0)

(t, f): (0, 1)

(int2011, int2014): (2011, 2014)

(int2011, int2014): (2014, 2011)

(first, second): (first, second)

(first, second): (second, first)

Explanation#
In the example above, we’ve declared two function templates: xchg and
nTimes in lines 8 and 15. xchg swaps the values passed as arguments. The
only non-type, we use is N in the function templates nTimes . nTimes returns
the N times of the number passed n . We have initialized multiple instances
to check for functions in lines 31 and 32, lines 39 and 40, and lines 46 and 47.

Example 2: Overloading Function


Templates#
1 // templateFunctionsTemplatesOverloading.cpp
2
3 #include <iostream>
4
5 void xchg(int& x, int& y){   // 1
6   int t = x;
7   x = y;
8   y = t;
9 }
10
11
12 template <typename T>        // 2
https://www.educative.io/courses/generic-templates-in-cpp/qZ1WEvv4nXD 3/6
3/20/22, 7:02 PM - Examples - Generic Programming Templates in C++
p yp //
13 void xchg(T& x, T& y){
14   T t = x;
15   x = y;
16   y = t;
17 }
18
19 template <typename T>         // 3
20 void xchg(T& x, T& y, T& z){
21   xchg(x, y);
22   xchg(x, z);
23 }
24
25 int main(){
26
27   std::cout << std::endl;
28
29   int intA = 5;
30   int intB = 10;
31   int intC = 20;
32
33   double doubleA = 5.5;
34   double doubleB = 10.0;
35
36   std::cout << "Before: " << intA << ", " << intB << std::endl;
37   xchg(intA, intB);              // 1
38   std::cout << "After: " << intA << ", " << intB << std::endl;
39
40   std::cout << std::endl;
41
42   std::cout << "Before: " << doubleA << ", " << doubleB << std::endl;
43   xchg(doubleA, doubleB);        // 2
44   std::cout << "After: " << doubleA << ", " << doubleB << std::endl;
45   
46   std::cout << std::endl;
47
48   xchg<>(intA, intB);            // explicit 2
49   xchg<int>(intA, intB);         // explicit 2: xchg<int>
50   // xchg<double>(intA, intB);      // ERROR explicit xchg<double>
51 (/learn)
52   std::cout << "Before: " << intA << ", " << intB << ", " << intC << std::endl;
53   xchg(intA, intB, intC);        // 3
54   std::cout << "After: " << intA << ", " << intB << ", " << intC << std::endl;
55
56   std::cout << std::endl;
57 }

https://www.educative.io/courses/generic-templates-in-cpp/qZ1WEvv4nXD 4/6
3/20/22, 7:02 PM - Examples - Generic Programming Templates in C++

Output 3.44s

Before: 5, 10

After: 10, 5

Before: 5.5, 10

After: 10, 5.5

Before: 10, 5, 20

After: 20, 10, 5

Explanation#
In the above example, we used the concept of function overloading by
calling xchg with different arguments passed to the function. We used the
xchg function with different data types by passing two arguments and three
arguments. In line 37, the non-template function is called, whereas, on all
other calls to xchg() , the template function is used. The call xchg<double>
(intA, intB) would be fine, when xchg would take its arguments by value.

In the next lesson, we’ll solve an exercise related to function templates.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

https://www.educative.io/courses/generic-templates-in-cpp/qZ1WEvv4nXD 5/6
3/20/22, 7:02 PM - Examples - Generic Programming Templates in C++

Back Next

Function Templates - Exercise

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qZ1WEvv4nXD 6/6
3/20/22, 5:30 PM - Exercise - Generic Programming Templates in C++

- Exercise (/learn)

In this lesson, we'll solve a challenge that attempts to compute the power of the expression.

We'll cover the following

• Problem Statement

Problem Statement#
You have to implement a function which calculates 210 in the program. Try
using templates to implement the function.

1 #include <iostream>
2
3 // Write your code here
4
5 int main() {
6   // Call function here
7 }

In the next lesson, we’ll look at the different ways to solve this exercise.

Back Next

- Examples - Solution

https://www.educative.io/courses/generic-templates-in-cpp/BnMO7PxOX6Q 1/2
3/20/22, 5:30 PM - Exercise - Generic Programming Templates in C++

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/BnMO7PxOX6Q 2/2
3/20/22, 5:31 PM - Solution - Generic Programming Templates in C++

- Solution
We'll learn different approaches to solve the previous challenge.

We'll cover the following

• Solution 1: Using Function Arguments

• Explanation
• Solution 2: Using Template Arguments

• Explanation
• Solution 3: Using Template Arguments and Function Arguments

• Explanation

Solution 1: Using Function


Arguments#
1 // power1.cpp
2
3 #include <iostream>
4
5 int power(int m, int n){
6   int r = 1;
7   for(int k=1; k<=n; ++k) r*= m;
8   return r;
9 }
10
11 int main(){
12   std::cout << power(2,10) << std::endl;
13 }

https://www.educative.io/courses/generic-templates-in-cpp/BnBZYxpxmQo 1/5
3/20/22, 5:31 PM - Solution - Generic Programming Templates in C++

Explanation#
We’re using a for loop to compute the power. The loop runs a total of n
times by multiplying the number m with r for every iteration of the loop in
line 7.

To get a more in-depth insight into the above solution, click here
(https://godbolt.org/z/p0kKAZ). It shows how things are handled at the
assembler level.

The critical point of this example is that the function runs at runtime.

Solution 2: Using Template


Arguments#
1 // power2.cpp
2
3 #include <iostream>
4
5 template<int m, int n>
6 struct Power{
7     static int const value = m * Power<m,n-1>::value;
8 };
9
10 template<int m>
11 struct Power<m,0>{
12    static int const value = 1;
13 };
14
15 int main(){
16    std::cout << Power<2,10>::value << std::endl;
17 }

https://www.educative.io/courses/generic-templates-in-cpp/BnBZYxpxmQo 2/5
3/20/22, 5:31 PM - Solution - Generic Programming Templates in C++

Explanation#
The call Power<2, 10>::value in line 16 triggers the recursive calculation.
First, the primary template in line 5 is called, then the Power<m, n-1>::value
in line 7 is executed. This expression instantiates recursively until the end
condition is met; n is equal to 0. Now, the boundary condition in line 12 is
applied, which returns 1. In the end, Power<2, 10>::value contains the
result.

To view how things are happening at the assembler level, click here
(https://godbolt.org/z/pjXrQm).

The critical point is that the calculation is done at compile-time.

Solution 3: Using Template


Arguments and Function Arguments#
1 // power3 .cpp
2
3 #include <iostream>
4
5 template<int n>
6 int power(int m){
7     return m * power<n-1>(m);
8 }
9
10 template<>
11 int power<1>(int m){
12     return m;
13 }
14 (/learn)
15 template<>
16 int power<0>(int m){
17     return 1;
18 }
19
https://www.educative.io/courses/generic-templates-in-cpp/BnBZYxpxmQo 3/5
3/20/22, 5:31 PM - Solution - Generic Programming Templates in C++
19
20 int main(){
21     std::cout << power<10>(2) << std::endl;
22 }

Explanation#
In the above code, the power function template exists in three variations.
First in the primary template in line 6. Second and third in the full
specializations for 1 and 0 in lines 11, and 16. The call power<10>(2) triggers
the recursive invocation of the primary template. The recursion ends with
the full specialization for 1. When you study the example carefully, you’ll see
that the full specialization for is not necessary in this case because the full
specialization for 0 is also a valid boundary condition.

When we invoke the power<10>(2) function, the argument in () brackets is


evaluated at runtime and the argument in <> brackets is evaluated at
compile-time. Therefore, we can say that the round brackets are run time
arguments and the angle brackets are compile-time arguments.

Let’s have a look at the assembler code and how they are managing this.
Click here (https://godbolt.org/z/wLujdp) to view the code.

In the lesson, we’ll learn about class templates in detail.

Back Next

- Exercise Class Templates


https://www.educative.io/courses/generic-templates-in-cpp/BnBZYxpxmQo 4/5
3/20/22, 5:31 PM - Solution - Generic Programming Templates in C++

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/BnBZYxpxmQo 5/5
3/20/22, 5:32 PM - Solution - Generic Programming Templates in C++

- Solution
We'll learn different approaches to solve the previous challenge.

We'll(/learn)
cover the following

• Solution 1: Using Function Arguments

• Explanation
• Solution 2: Using Template Arguments
• Explanation
• Solution 3: Using Template Arguments and Function Arguments

• Explanation

Solution 1: Using Function


Arguments#
1 // power1.cpp
2
3 #include <iostream>
4
5 int power(int m, int n){
6   int r = 1;
7   for(int k=1; k<=n; ++k) r*= m;
8   return r;
9 }
10
11 int main(){
12   std::cout << power(2,10) << std::endl;
13 }

https://www.educative.io/courses/generic-templates-in-cpp/BnBZYxpxmQo 1/5
3/20/22, 5:32 PM - Solution - Generic Programming Templates in C++

Explanation#
We’re using a for loop to compute the power. The loop runs a total of n
times by multiplying the number m with r for every iteration of the loop in
line 7.

To get a more in-depth insight into the above solution, click here
(https://godbolt.org/z/p0kKAZ). It shows how things are handled at the
assembler level.

The critical point of this example is that the function runs at runtime.

Solution 2: Using Template


Arguments#
// power2.cpp

#include <iostream>

template<int m, int n>

struct Power{

static int const value = m * Power<m,n-1>::value;

};

template<int m>

struct Power<m,0>{

static int const value = 1;

};

int main(){

std::cout << Power<2,10>::value << std::endl;

https://www.educative.io/courses/generic-templates-in-cpp/BnBZYxpxmQo 2/5
3/20/22, 5:32 PM - Solution - Generic Programming Templates in C++

Explanation#
The call Power<2, 10>::value in line 16 triggers the recursive calculation.
First, the primary template in line 5 is called, then the Power<m, n-1>::value
in line 7 is executed. This expression instantiates recursively until the end
condition is met; n is equal to 0. Now, the boundary condition in line 12 is
applied, which returns 1. In the end, Power<2, 10>::value contains the
result.

To view how things are happening at the assembler level, click here
(https://godbolt.org/z/pjXrQm).

The critical point is that the calculation is done at compile-time.

Solution 3: Using Template


Arguments and Function Arguments#
// power3 .cpp

#include <iostream>

template<int n>

int power(int m){


return m * power<n-1>(m);

template<>

int power<1>(int m){

return m;

template<>

int power<0>(int m){

return 1;

int main(){
https://www.educative.io/courses/generic-templates-in-cpp/BnBZYxpxmQo 3/5
3/20/22, 5:32 PM - Solution - Generic Programming Templates in C++
int main(){

std::cout << power<10>(2) << std::endl;

Explanation#
In the above code, the power function template exists in three variations.
First in the primary template in line 6. Second and third in the full
specializations for 1 and 0 in lines 11, and 16. The call power<10>(2) triggers
the recursive invocation of the primary template. The recursion ends with
the full specialization for 1. When you study the example carefully, you’ll see
that the full specialization for is not necessary in this case because the full
specialization for 0 is also a valid boundary condition.

When we invoke the power<10>(2) function, the argument in () brackets is


evaluated at runtime and the argument in <> brackets is evaluated at
compile-time. Therefore, we can say that the round brackets are run time
arguments and the angle brackets are compile-time arguments.

Let’s have a look at the assembler code and how they are managing this.
Click here (https://godbolt.org/z/wLujdp) to view the code.

In the lesson, we’ll learn about class templates in detail.

Back Next

- Exercise Class Templates

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/BnBZYxpxmQo 4/5
3/20/22, 5:32 PM - Solution - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/BnBZYxpxmQo 5/5
3/20/22, 7:08 PM Class Templates - Generic Programming Templates in C++

Class Templates
In this lesson, we'll learn about the class templates.

We'll cover the following

• Syntax

• Explanation
• Instantiation

• Method Templates
• Inheritance

• 3 Solutions:

• Templates: Alias Templates

A class template defines a family of classes.

Syntax#
template < parameter-list > 

class-declaration       

Explanation#
parameter-list: A non-empty comma-separated list of the template
parameters, each of which is either a non-type parameter, a type parameter,
a template parameter, or a mixture of any of those.

class-declaration: A class declaration. The class name declared becomes a


https://www.educative.io/courses/generic-templates-in-cpp/JEM9l4NrKZJ 1/5
3/20/22, 7:08 PM Class Templates - Generic Programming Templates in C++
class declaration: A class declaration. The class name declared becomes a
template name.

Instantiation#
The process of substituting the template parameters with the template
arguments is called instantiation .

In contrast to a function template, a class template is not capable of


automatically deriving the template parameters.
Each template
argument must be explicitly specified. This restriction no longer exists
with C++17.

Let’s have a look at the declaration of function and class templates:

Function Template Class Template


Declaration Declaration
template <typename T>
template <typename T, int N>

void xchg(T& x, T&y){
class Array{

...
...

}
};

int a, b;
Array<double, 10> doubleArray;

xchg(a, b);
Array<Account, 1000> accountArray
;

Method Templates#
Method templates are function templates used in a class or class template.

https://www.educative.io/courses/generic-templates-in-cpp/JEM9l4NrKZJ 2/5
3/20/22, 7:08 PM Class Templates - Generic Programming Templates in C++

Method templates can be defined inside or outside the class. When you
define the method template outside the class, the syntax is quite
complicated because you have to repeat the class template declaration
and the method template declaration.

Let’s have a look at the declaration of the method template inside the class
and its definition outside the class:

1 template <class T, int N> class Array{
2 public:
3   template <class T2>
4   Array<T, N>& operator = (const Array<T2, N>& a); ...
5 };
6
7 template<class T, int N>
8 template<class T2>
9   Array<T, N>& Array<T, N>::operator = (const Array<T2, N>& a{
10   ...
11   }

The destructor and copy constructor cannot be templates.

Inheritance#
Class and class template can inherit from each other in arbitrary
combinations.

If a class or a class template inherits from a class template, the methods


of the base class or base class template are not automatically available
in the derived class.

https://www.educative.io/courses/generic-templates-in-cpp/JEM9l4NrKZJ 3/5
3/20/22, 7:08 PM Class Templates - Generic Programming Templates in C++

1 template <typename T>
2 struct Base{
3   void func(){ ...
4 };
5
6 template <typename T> struct Derived: Base<T>{
7   void func2(){
8   func();       // ERROR
9   }
10 }

There are three ways to make a method from the derived class template
available.
(/learn)

3 Solutions:#
Qualification via this pointer: this->func()
Introducing the name using Base<T>::func

Full qualified access Base<T>::func()

Templates: Alias Templates#


Alias templates, aka template typedefs, allow you to give a name to partially
bound templates. An example of partial specialization from templates is
given below:

1 template <typename T, int Line, int Col> class Matrix{
2 ...
3 };
4
5 template <typename T, int Line>
6 using Square = Matrix<T, Line, Line>;
7
8 template <typename T, int Line>
9 using Vector = Matrix<T, Line, 1>;
10
11 Matrix<int, 5, 3> ma;
12 Square<double, 4> sq;
13 Vector<char, 5> vec;
https://www.educative.io/courses/generic-templates-in-cpp/JEM9l4NrKZJ 4/5
3/20/22, 7:08 PM Class Templates - Generic Programming Templates in C++
, ;

To learn more about class templates, click here


(https://en.cppreference.com/w/cpp/language/class_template).

In the next lesson, we’ll learn about the examples of class templates.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solution - Examples

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/JEM9l4NrKZJ 5/5
3/20/22, 7:03 PM - Examples - Generic Programming Templates in C++

- Examples
In this lesson, we'll learn about the examples of class templates.

We'll cover the following

• Example 1: Templates in Class

• Explanation
• Example 2: Inheritance in Class Templates

• Explanation
• Example 3: Methods in Class Templates

• Explanation

Example 1: Templates in Class#


1 // templateClassTemplate.cpp
2
3 #include <iostream>
4
5 class Account{
6 public:
7   explicit Account(double amount=0.0): balance(amount){}
8
9   void deposit(double amount){
10     balance+= amount;
11   }
12
13   void withdraw(double amount){
14     balance-= amount;
15   }
16   
17   double getBalance() const{
18     return balance;
19 }
https://www.educative.io/courses/generic-templates-in-cpp/7DxJ7y5k0Zj 1/7
3/20/22, 7:03 PM - Examples - Generic Programming Templates in C++
19   }
20
21 private:
22   double balance;
23 };
24
25 template <typename T, int N>
26 class Array{
27
28 public:
29   Array()= default;
30   int getSize() const;
31
32 private:
33   T elem[N];
34 };
35
36 template <typename T, int N>
37 int Array<T,N>::getSize() const {
38   return N;
39 }
40
41 int main(){
42
43   std::cout << std::endl;
44
45   Array<double,10> doubleArray;
46   std::cout << "doubleArray.getSize(): " << doubleArray.getSize() << std::endl;
47
48   Array<Account,1000> accountArray;
49   std::cout << "accountArray.getSize(): " << accountArray.getSize() << std::endl;
50
51   std::cout << std::endl;
52 }

Output 1.28s

doubleArray.getSize(): 10

accountArray.getSize(): 1000

https://www.educative.io/courses/generic-templates-in-cpp/7DxJ7y5k0Zj 2/7
3/20/22, 7:03 PM - Examples - Generic Programming Templates in C++

Explanation#
We have created two Array class objects, i.e., doubleArray and accountArray
in lines 45 and 48. By calling generic function getSize() in line 37, we can
access the size of different objects.

Example 2: Inheritance in Class


Templates#
1 // templateClassTemplateInheritance.cpp
2
3 #include <iostream>
4
5 template <typename T>
6 class Base{
7 public:
8   void func1() const {
9     std::cout << "func1()" << std::endl;
10   }
11   void func2() const {
12     std::cout << "func2()" << std::endl;
13   }
14   void func3() const {
15     std::cout << "func3()" << std::endl;
16   }
17 };
18
19 template <typename T>
20 class Derived: public Base<T>{
21 public:
22   using Base<T>::func2;
23   
24   void callAllBaseFunctions(){
25     this->func1();
26     func2();
27     Base<T>::func3();
28   }
29 };
30
31 int main(){
https://www.educative.io/courses/generic-templates-in-cpp/7DxJ7y5k0Zj 3/7
3/20/22, 7:03 PM - Examples - Generic Programming Templates in C++
32   std::cout << std::endl;
33
34   Derived<int> derived;
35   derived.callAllBaseFunctions();
36
37   std::cout << std::endl;
38 }

Output 2.23s

func1()

func2()

func3()

Explanation#
We have implemented both a Base and a Derived class. Derived is publicly
inherited from Base and may, therefore, use in its method
callAllBaseFunctions in line 24, the methods func1 , func2 , and func3 from
the Base class.

Make the name dependent: The call this->func1 in line 25 is


dependent. The name lookup will consider in this case all base classes.

Introduce the name into the current scope: The expression using
Base<T>::func2 (line 22) introduces func2 into the current scope.

Call the name fully qualified: Calling func3 fully qualified (line 27)
will break a virtual dispatch and may cause new surprises.

https://www.educative.io/courses/generic-templates-in-cpp/7DxJ7y5k0Zj 4/7
3/20/22, 7:03 PM - Examples - Generic Programming Templates in C++

We have created a Derived class object named derived . By using this object,
we can access the base class functions by calling the method
callAllBaseFunctions .

Example 3: Methods in Class


Templates#
1 // templateClassTemplateMethods.cpp
2
3 #include <algorithm>
4 #include <iostream>
5 #include <vector>
6
7 template <typename T, int N>
8 class Array{
9
10 public:
11   Array()= default;
12
13   template <typename T2>
14   Array<T, N>& operator=(const Array<T2, N>& arr){
15     elem.clear();
16     elem.insert(elem.begin(), arr.elem.begin(), arr.elem.end());
17     return *this;
18   }
19
20   int getSize() const;
21
22   std::vector<T> elem;
23 };
24
25 template <typename T, int N>
26 (/learn)
int Array<T, N>::getSize() const {
27   return N;
28 }
29
30 int main(){
31
32   Array<double, 10> doubleArray{};
33   Array<int, 10> intArray{};
34
35 doubleArray= intArray;
https://www.educative.io/courses/generic-templates-in-cpp/7DxJ7y5k0Zj 5/7
3/20/22, 7:03 PM - Examples - Generic Programming Templates in C++
35   doubleArray= intArray;
36
37   Array<std::string, 10> strArray{};
38   Array<int, 100> bigIntArray{};
39
40   // doubleArray= strArray;            // ERROR: cannot convert ‘const std::basic_st
41   // doubleArray= bigIntArray;         // ERROR: no match for ‘operator=’ in ‘double
42 }

Succeeded

Explanation#
In the example above, we have initialized two instances of Array class
namely doubleArray and intArray in lines 32 and 33. We’re using the
generic = operator to copy the intArray elements to doubleArray in line 35.
When you look carefully, you see that the generic = is only applicable, when
both arrays have the same length.

In the next lesson, we have a small challenge for you to test your knowledge
of class templates.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

https://www.educative.io/courses/generic-templates-in-cpp/7DxJ7y5k0Zj 6/7
3/20/22, 7:03 PM - Examples - Generic Programming Templates in C++

Back Next

Class Templates - Exercise

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/7DxJ7y5k0Zj 7/7
3/20/22, 7:09 PM - Exercise - Generic Programming Templates in C++

- Exercise
Let's do a quick exercise on class templates.

We'll cover the following

• Problem Statement

Problem Statement#
Uncomment the final assignment doubleArray = strArray in line 41 and use
the function static_assert in combination with the function
std::is_convertible to catch the erroneous instantiation at compile-time.

1 #include <algorithm>
2 #include <iostream>
3 #include <vector>
4
5 template <typename T, int N>
6 class Array{
7
8 public:
9   Array()= default;
10
11   template <typename T2>
12   Array<T, N>& operator=(const Array<T2, N>& arr){
13     // write your code here
14     // uncomment line 41 to check if your code runs fine
15
16     elem.clear();
17     elem.insert(elem.begin(), arr.elem.begin(), arr.elem.end());
18     return *this;
19   }
20
21   int getSize() const;
22
https://www.educative.io/courses/generic-templates-in-cpp/xlrKg7OpKwl 1/3
3/20/22, 7:09 PM - Exercise - Generic Programming Templates in C++

23   std::vector<T> elem;
24 };
25
26 template <typename T, int N>
27 int Array<T, N>::getSize() const {
28   return N;
29 }
30 (/learn)
31 int main(){
32
33   Array<double, 10> doubleArray{};
34   Array<int, 10> intArray{};
35
36   doubleArray= intArray;
37
38   Array<std::string, 10> strArray{};
39   Array<int, 100> bigIntArray{};
40
41   //doubleArray= strArray;            // ERROR: cannot convert ‘const std::basic_str
42   // doubleArray= bigIntArray;         // ERROR: no match for ‘operator=’ in ‘double
43
44 }

Succeeded

In the next lesson, we’ll look at the solution to this problem.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

https://www.educative.io/courses/generic-templates-in-cpp/xlrKg7OpKwl 2/3
3/20/22, 7:09 PM - Exercise - Generic Programming Templates in C++

Back Next

- Examples - Solution

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/xlrKg7OpKwl 3/3
3/20/22, 7:16 PM - Solution - Generic Programming Templates in C++

- Solution
Let's review the solution of the previous problem in this lesson.

We'll cover the following

• Solution Review

• Explanation

Solution Review#
1 // templateClassTemplateMethods.cpp
2 #include <type_traits>
3 #include <algorithm>
4 #include <iostream>
5 #include <vector>
6
7 template <typename T, int N>
8 class Array{
9
10 public:
11   Array()= default;
12
13   template <typename T2>
14   Array<T,N>& operator=(const Array<T2, N>& arr){
15     static_assert(std::is_convertible<T2, T>::value, "Cannot convert source type to 
16     elem.clear();
17     elem.insert(elem.begin(), arr.elem.begin(), arr.elem.end());
18     return *this;
19   }
20
21   int getSize() const;
22
23   std::vector<T> elem;
24 };
25
26 template <typename T, int N>
https://www.educative.io/courses/generic-templates-in-cpp/g7ZOpwpW4j3 1/3
3/20/22, 7:16 PM - Solution - Generic Programming Templates in C++

27 int Array<T, N>::getSize() const {
28   return N;
29 }
30
31
32 int main(){
33
34   Array<double, 10> doubleArray{};
35   Array<int, 10> intArray{};
36
37   doubleArray= intArray;
38
39   Array<std::string, 10> strArray{};
40   Array<int, 100> bigIntArray{};
41
42   // doubleArray= strArray;            // ERROR: cannot convert ‘const std::basic_st
43   // doubleArray= bigIntArray;         // ERROR: no match for ‘operator=’ in ‘double
44
45 }

(/learn)
Succeeded

Explanation#
In the above code, we have created two arrays of int and double types in
lines 34 and 35. We’re copying the data of integer array to double array in
line 37. If we try to copy the string array data to double type in line 42, this
gives us an error because of the type mismatch. To see for yourself
uncomment the line and run to check the error. The function
std::is_convertible (https://en.cppreference.com/w/cpp/types/is_convertible)
in line 15 from the type-traits
(https://www.educative.io/collection/page/10370001/5799373671759872/6380
229176066048) library checks if one type can be converted to the other. Of
course, it is not possible to convert string into double .
https://www.educative.io/courses/generic-templates-in-cpp/g7ZOpwpW4j3 2/3
3/20/22, 7:16 PM - Solution - Generic Programming Templates in C++

Let’s move on to template parameters in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise Template Parameters

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/g7ZOpwpW4j3 3/3
3/20/22, 5:36 PM Template Parameters - Generic Programming Templates in C++

(/learn)

Template Parameters
Let's familiarize ourselves with template parameters in this lesson.

We'll cover the following

• Template Parameter

• Types
• Non-Types

Template Parameter#
Every template is parameterized by one or more template parameters,
indicated in the parameter-list of the template.

C++ supports three different kinds of template parameters

1. Type parameter

std::vector<int> vec = {1, 2, 3, 4, 5}; 

2. Non-type parameter

std::array<int, 5> arr = {1, 2, 3, 4, 5};

3. Template-template parameter

template <typename T, template <typename, typename> class Cont> class Ma
trix{

...

https://www.educative.io/courses/generic-templates-in-cpp/JYv86M3D2EP 1/3
3/20/22, 5:36 PM Template Parameters - Generic Programming Templates in C++

Matrix<int, std::vector> myIntVec;

Types#
A type parameter is a typical case for template arguments.

Type parameters are class types and fundamental types

Non-Types#
Non-types are template parameters which can be evaluated at compile-time.

The following types are possible

Integers and enumerations

Pointers to objects, functions, and attributes of a class

References to objects and functions

std::nullptr_t constant

With C++17, floating-point numbers and strings cannot be used as non-


type parameters.

To learn more about template parameters, click here


(https://en.cppreference.com/w/cpp/language/template_parameters).

In the next lesson, we’ll look at the examples of the three different types of
template parameters.

https://www.educative.io/courses/generic-templates-in-cpp/JYv86M3D2EP 2/3
3/20/22, 5:36 PM Template Parameters - Generic Programming Templates in C++

Back Next

Solution Examples
Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/JYv86M3D2EP 3/3
3/20/22, 7:17 PM - Examples - Generic Programming Templates in C++

- Examples
In this lesson, we'll learn about the examples of template parameters.

We'll cover the following

• Example 1: Type Parameter

• Explanation
• Example 2: Non-Type Template Parameter

• Explanation
• Example 3: Template-Template Parameter

• Explanation

Example 1: Type Parameter#


1 // templateTypeParameter.cpp
2
3 #include <iostream>
4 #include <typeinfo>
5
6 class Account{
7 public:
8   explicit Account(double amt): balance(amt){}
9 private:
10   double balance;
11
12 };
13
14 union WithString{
15   std::string s;
16   int i;
17   WithString():s("hello"){}
18   ~WithString(){}
19 };
https://www.educative.io/courses/generic-templates-in-cpp/gk9Eq0rPLxZ 1/7
3/20/22, 7:17 PM - Examples - Generic Programming Templates in C++
19 };
20
21 template <typename T>
22 class ClassTemplate{
23 public:
24   ClassTemplate(){
25     std::cout << "typeid(T).name(): "  << typeid(T).name() << std::endl;
26   }
27 };
28
29 int main(){
30
31   std::cout << std::endl;
32
33   ClassTemplate<int> clTempInt;
34   ClassTemplate<double> clTempDouble;
35   ClassTemplate<std::string> clTempString;
36
37   ClassTemplate<Account> clTempAccount;
38   ClassTemplate<WithString> clTempWithString;
39
40   std::cout << std::endl;
41
42 }

Output 1.82s

typeid(T).name(): i

typeid(T).name(): d

typeid(T).name(): NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

typeid(T).name(): 7Account

typeid(T).name(): 10WithString

Explanation#
In the above code, we are identifying the type of different data types that we
have passed in the parameter list We can identify the type of variable
https://www.educative.io/courses/generic-templates-in-cpp/gk9Eq0rPLxZ 2/7
3/20/22, 7:17 PM - Examples - Generic Programming Templates in C++
have passed in the parameter list. We can identify the type of variable
passed to the function by using the keyword typeid in line 25. If we pass

string or class type object in the parameter list, it will display the type of
parameter passed along with the size of the object.

Example 2: Non-Type Template


Parameter#
1 // array.cpp
2
3 #include <algorithm>
4 #include <array>
5 #include <iostream>
6
7 int main(){
8
9   std::cout << std::endl;
10
11   // output the array
12   std::array <int,8> array1{1,2,3,4,5,6,7,8};
13   std::for_each( array1.begin(),array1.end(),[](int v){std::cout << v << " ";});
14
15   std::cout << std::endl;
16
17   // calculate the sum of the array by using a global variable
18   int sum = 0;
19   std::for_each(array1.begin(), array1.end(),[&sum](int v) { sum += v; });
20   std::cout << "sum of array{1,2,3,4,5,6,7,8}: " << sum << std::endl;
21
22   // change each array element to the second power
23   std::for_each(array1.begin(), array1.end(),[](int& v) { v=v*v; });
24   std::for_each( array1.begin(),array1.end(),[](int v){std::cout << v << " ";});
25   std::cout << std::endl;
26
27   std::cout << std::endl;
28 }

https://www.educative.io/courses/generic-templates-in-cpp/gk9Eq0rPLxZ 3/7
3/20/22, 7:17 PM - Examples - Generic Programming Templates in C++

Output 1.93s

1 2 3 4 5 6 7 8

sum of array{1,2,3,4,5,6,7,8}: 36
1 4 9 16 25 36 49 64

Explanation#
When you define an std::array in line 12, you have to specify its size. The
size is a non-type template argument, which has to be specified at compile-
time.

Therefore, you can output array1 in line 13 with a lambda-function [] and


the range-based for-loop. By using the summation variable sum in line 19,
you can sum up the elements of the std::array . The lambda-function in line
23 takes its arguments by reference and can, therefore, map each element to
its square. There is nothing really special, but we are dealing with an
std::array .

With C++11 we have the free function templates std::begin and std::end
returning iterators for a C array. A C array is quite comfortable and safe to
use with these function templates because we don’t have to remember its
size.

Example 3: Template-Template
Parameter#
1 // t l t T l t T l t P
https://www.educative.io/courses/generic-templates-in-cpp/gk9Eq0rPLxZ
t 4/7
3/20/22, 7:17 PM - Examples - Generic Programming Templates in C++
1 // templateTemplateTemplatesParameter.cpp
2
3 #include <initializer_list>
4 #include <iostream>
5 #include <list>
6 #include <vector>
7
8 template <typename T, template <typename, typename> class Cont >
9 class Matrix{
10 public:
11   explicit Matrix(std::initializer_list<T> inList): data(inList){
12     for (auto d: data) std::cout << d << " ";
13   }
14   int getSize() const{
15     return data.size();
16   }
17
18 private:
19   Cont<T, std::allocator<T>> data;
20
21 };
22
23 int main(){
24
25   std::cout << std::endl;
26
27   Matrix<int,std::vector> myIntVec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
28   std::cout << std::endl;
29   std::cout << "myIntVec.getSize(): " << myIntVec.getSize() << std::endl;
30
31   std::cout << std::endl;
32
33   Matrix<double,std::vector> myDoubleVec{1.1, 2.2, 3.3, 4.4, 5.5};
34   std::cout << std::endl;
35   std::cout << "myDoubleVec.getSize(): "  << myDoubleVec.getSize() << std::endl;
36
37   std::cout << std::endl;
38
39   Matrix<std::string,std::list> myStringList{"one", "two", "three", "four"};
40   std::cout << std::endl;
41   std::cout << "myStringList.getSize(): " << myStringList.getSize() << std::endl;
42
43   std::cout << std::endl;
44 }

(/learn)
https://www.educative.io/courses/generic-templates-in-cpp/gk9Eq0rPLxZ 5/7
3/20/22, 7:17 PM - Examples - Generic Programming Templates in C++
(/learn)

Output 1.56s

1 2 3 4 5 6 7 8 9 10

myIntVec.getSize(): 10

1.1 2.2 3.3 4.4 5.5

myDoubleVec.getSize(): 5

one two three four

myStringList.getSize(): 4

Explanation#
We have declared a Matrix class which contains a function, i.e., getSize ,
and an explicit constructor that prints all entries of the passed parameter.
Cont in line 8 is a template, which takes two arguments. There’s no need for
us to name the template parameters in the template declaration. We have to
specify them in the instantiation of the template (line 19). The template used
in the template parameter has exactly the signature of the sequence
containers (https://en.cppreference.com/w/cpp/container). The result is, that
we can instantiate a matrix with an std::vector , or an std::list . Of course
std::deque and std::forward_list would also be possible. In the end, you
have a Matrix , which stores its elements in a vector or in a list.

If you want to study more examples for template-template parameter, you


can check container adaptors (https://en.cppreference.com/w/cpp/container).

We’ll be solving a small exercise on template parameters in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


https://www.educative.io/courses/generic-templates-in-cpp/gk9Eq0rPLxZ 6/7
3/20/22, 7:17 PM - Examples - Generic Programming Templates in C++
Interviewing soon? We ve partnered with Hired so that companies apply to
you instead of you applying to them. See how

(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Template Parameters - Exercise

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/gk9Eq0rPLxZ 7/7
3/20/22, 5:38 PM - Exercise - Generic Programming Templates in C++

(/learn)

- Exercise
Let's solve an exercise in this lesson.

We'll cover the following

• Problem Statement

Problem Statement#
Implement four different class templates which accept an integral, a pointer,
a reference, or a nullptr as a non-type parameter. You need to display the
type of data passed as a parameter.

1 #include <iostream>
2
3 // Write class templates for given commented code
4
5
6 int main() {
7   // uncomment these lines after implementing codes
8
9   /*
10   AcceptChar<'c'> acceptChar;
11   AcceptFunction< myFunc> acceptFunction;
12   AcceptReference< arr > acceptReference;
13   AcceptNullptr< nullptr > acceptNullptr;
14   */
15 }

https://www.educative.io/courses/generic-templates-in-cpp/B1QQ5241XWo 1/2
3/20/22, 5:38 PM - Exercise - Generic Programming Templates in C++

In the next lesson, we’ll look at the solution to this exercise.

Back Next

- Examples - Solution

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/B1QQ5241XWo 2/2
3/20/22, 7:18 PM - Solution - Generic Programming Templates in C++

- Solution
In this lesson, we'll look at the solution review of the previous challenge.

We'll cover the following

• Solution Review

• Explanation

Solution Review#
1 #include <cstddef>
2 #include <iostream>
3 #include <typeinfo>
4
5 template <char c>
6 class AcceptChar{
7 public:
8   AcceptChar(){
9     std::cout << "AcceptChar: "  << typeid(c).name() << std::endl;
10   }
11 };
12
13 template < int(*func)(int) >
14 class AcceptFunction{
15 public:
16   AcceptFunction(){
17     std::cout << "AcceptFunction: "  << typeid(func).name() << std::endl;
18   }
19 };
20
21 template < int(&arr)[5] >
22 class AcceptReference{
23 public:
24   AcceptReference(){
25     std::cout << "AcceptReference: " << typeid(arr).name() << std::endl;
26   }
https://www.educative.io/courses/generic-templates-in-cpp/xlKWvlmxVVJ 1/3
3/20/22, 7:18 PM - Solution - Generic Programming Templates in C++

27 };
28
29 template < std::nullptr_t N >
30 class AcceptNullptr{
31 public:
32   AcceptNullptr(){
33     std::cout << "AcceptNullpt: " << typeid(N).name() << std::endl;
34   }
35 };
36
37 int myFunc(int){ return 2011; };
38 int arr[5];
39
40 int main(){
41
42   std::cout << std::endl;
43
44   AcceptChar<'c'> acceptChar;
45   AcceptFunction< myFunc> acceptFunction;
46   AcceptReference< arr > acceptReference;
47   AcceptNullptr< nullptr > acceptNullptr;
48
49   std::cout << std::endl;
50
51 }
52

(/learn)

Output 1.29s

AcceptChar: c

AcceptFunction: PFiiE

AcceptReference: A5_i

AcceptNullpt: Dn

Explanation#
https://www.educative.io/courses/generic-templates-in-cpp/xlKWvlmxVVJ 2/3
3/20/22, 7:18 PM - Solution - Generic Programming Templates in C++

We have created four different class templates which include AcceptChar ,


AcceptFunction , AcceptReference , and AcceptNull in lines 6, 14, 22, and 30.
Each class template accepts a different non-type. To verify all, we have
declared a character variable, a reference to an array, a function, and
nullptr in lines 44 – 47. This matches the order of declaration in the code.
We identify their type using the operator typeid in lines 9, 17, 25, and 33.

Let’s move on to template arguments in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise Template Arguments

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/xlKWvlmxVVJ 3/3
3/20/22, 5:38 PM Template Arguments - Generic Programming Templates in C++

(/learn)

Template Arguments
In this lesson, we'll learn about template arguments.

We'll cover the following

• Template Arguments

• Template Arguments (C++17)


• Argument Deduction

• Explicit Template Arguments


• Default Template Arguments

Template Arguments#
Template arguments can, in general, automatically be deduced for function
templates.
The compiler deduces the template arguments for the function
arguments. From the user’s perspective, function templates feel like
functions.

Conversion:

The compiler uses simple conversions for deducing the template


arguments from the function arguments.
The compiler removes const or volatile from the function arguments
and converts C-arrays and functions to pointers.

Template argument deduction for function templates:

template <typename T>


https://www.educative.io/courses/generic-templates-in-cpp/m2rWRJGYmVG 1/5
3/20/22, 5:38 PM Template Arguments - Generic Programming Templates in C++
template <typename T>

void func(ParamType param);

Two datatypes were deduced:

ParamType

ParamType can be

Reference or pointer

Universal reference( && )


Value (copy)

1. The parameter type is a reference or a pointer

  template <typename T>

  void func(T& param);

  // void func(T* param);

  func(expr);

T ignores reference or pointer

Pattern matching on expr for T& or T

2. The parameter type is a universal reference ( && )

  template <typename T>

  void func(T&& param);

  func(expr);

expr is an lvalue: T and ParamType become lvalue references


expr is an rvalue: T is deduced such as the ParamType is a reference
(case 1)

3. Parameter type is a value (copy)

  template <typename T>

void func(T param);


https://www.educative.io/courses/generic-templates-in-cpp/m2rWRJGYmVG 2/5
3/20/22, 5:38 PM Template Arguments - Generic Programming Templates in C++
  void func(T param);

  func(expr);

1. expr is a reference: the reference (pointer) of the argument is ignored

2. expr is const or volatile : const or volatile is ignored

Template Arguments (C++17)#


The constructor can deduce its template arguments from its function
arguments.

Template Argument deduction for a constructor is available since C++17, but


for function templates since C++98.

  std::pair<int, double> myPair(2011, 1.23);

  std::pair myPair(2011, 1.23);

Many of the make_ functions such as std::make_pair are not necessary any
more:

  auto myPair = std::make_pair(2011, 1.23);

Argument Deduction#
The types of function arguments have to be exact, otherwise, no conversion
takes place.

template <typename T>

bool isSmaller(T fir, T sec){

return fir < sec;

isSmaller(1, 5LL); // ERROR int != long long int

Providing a second template parameter makes this


example work.
https://www.educative.io/courses/generic-templates-in-cpp/m2rWRJGYmVG 3/5
3/20/22, 5:38 PM Template Arguments - Generic Programming Templates in C++
g p p p

template <typename T, typename U>

bool isSmaller(T fir, U sec){

return fir < sec;

isSmaller(1, 5LL); // OK

Explicit Template Arguments#


Unlike in line 5 in the previous example, sometimes the template argument
types need to be explicitly specified. This is necessary in the following cases:

Explicit Template Arguments

if the template argument cannot be deduced from the function


argument.

if a specific instance of a function template is needed.

template <typename R, typename T, typename U>

R add(T fir, U sec){

   return fir * sec;

add<long long int>(1000000, 1000000LL);

Missing template arguments are automatically derived from the


function arguments.

Default Template Arguments#


The default for template parameters can be specified for class templates and
function templates. If a template parameter has a default parameter, all
subsequent template parameters also need a default argument.

https://www.educative.io/courses/generic-templates-in-cpp/m2rWRJGYmVG 4/5
3/20/22, 5:38 PM Template Arguments - Generic Programming Templates in C++

template <typename T, typename Pred = std::less<T>>

bool isSmaller(T fir, T sec, Pred pred = Pred()){

  return pred(fir, sec);

To learn more about template arguments, click here


(https://en.cppreference.com/w/cpp/language/template_argument_deduction
).

In the next lesson, we’ll take a look at the examples of template arguments.

Back Next

- Solution - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/m2rWRJGYmVG 5/5
3/20/22, 8:01 PM - Examples - Generic Programming Templates in C++

(/learn)

- Examples
Let's check out the examples of template arguments.

We'll cover the following

• Example 1: Deduction of Template Arguments

• Explanation
• Example 2: Template Default Arguments

• Explanation
• Example 3: Function Template Argument Deduction by Reference

• Explanation

• Example 4: Function Template Argument Deduction by Universal


Reference

• Explanation
• Example 5: Function Template Argument Deduction by Value
• Explanation

Example 1: Deduction of Template


Arguments#
1 // templateArgumentDeduction.cpp
2
3 #include <iostream>
4
5 template <typename T>
6 bool isSmaller(T fir, T sec){
7 return fir < sec;
https://www.educative.io/courses/generic-templates-in-cpp/m20Mg8J806A 1/10
3/20/22, 8:01 PM - Examples - Generic Programming Templates in C++
7   return fir < sec;
8 }
9
10 template <typename T, typename U>
11 bool isSmaller2(T fir, U sec){
12   return fir < sec;
13 }
14
15 template <typename R, typename T, typename U>
16 R add(T fir, U sec){
17   return fir + sec;
18 }
19
20 int main(){
21
22   std::cout << std::boolalpha << std::endl;
23
24   std::cout << "isSmaller(1,2): " << isSmaller(1,2) << std::endl;
25   // std::cout << "isSmaller(1,5LL): "  << isSmaller(1,5LL) << std::endl; // ERROR
26
27   std::cout << "isSmaller<int>(1,5LL): " << isSmaller<int>(1,5LL) << std::endl;
28   std::cout << "isSmaller<double>(1,5LL): " << isSmaller<double>(1,5LL) << std::endl
29
30   std::cout << std::endl;
31
32   std::cout << "isSmaller2(1,5LL): "  << isSmaller2(1,5LL) << std::endl;
33
34   std::cout << std::endl;
35
36   std::cout << "add<long long int>(1000000,1000000): " << add<long long int>(1000000
37   std::cout << "add<double,double>(1000000,1000000): " << add<double,double>(1000000
38   std::cout << "add<double,double,float>(1000000,1000000): " << add<double,double,fl
39
40   std::cout << std::endl;
41 }

Output 1.65s

isSmaller(1,2): true

isSmaller<int>(1,5LL): true

isSmaller<double>(1,5LL): true

isSmaller2(1 5LL): true


https://www.educative.io/courses/generic-templates-in-cpp/m20Mg8J806A 2/10
3/20/22, 8:01 PM - Examples - Generic Programming Templates in C++
isSmaller2(1,5LL): true

add<long long int>(1000000,1000000): 2000000

add<double,double>(1000000,1000000): 2e+06

Explanation#
In the above example, we have defined 3 function templates

isSmaller takes two arguments which have the same type and returns
true if the first element is less than the second element (line 6).
Invoking the function with arguments of different types would give a
compile-time error (line 25).

isSmaller2 takes two arguments which can have a different type. The
function returns true if the first element is less than the second
element (line 11).
add takes two arguments which can have different types (line 16). The
return type must be specified because it cannot be deduced from the
function arguments.

Example 2: Template Default


Arguments#
1 // templateDefaultArgument.cpp
2
3 #include <functional>
4 #include <iostream>
5 #include <string>
6
7 class Account{
8 public:
9   explicit Account(double b): balance(b){}
10   double getBalance() const {
11     return balance;
12   }
13 private:
https://www.educative.io/courses/generic-templates-in-cpp/m20Mg8J806A 3/10
3/20/22, 8:01 PM - Examples - Generic Programming Templates in C++

14   double balance;
15 };
16
17 template <typename T, typename Pred= std::less<T> >
18 bool isSmaller(T fir, T sec, Pred pred= Pred() ){
19   return pred(fir,sec);
20 }
21
22 int main(){
23
24   std::cout << std::boolalpha << std::endl;
25
26   std::cout << "isSmaller(3,4): " << isSmaller(3,4) << std::endl;
27   std::cout << "isSmaller(2.14,3.14): "  << isSmaller(2.14,3.14) << std::endl;
28   std::cout << "isSmaller(std::string(abc),std::string(def)): " << isSmaller(std::st
29
30   bool resAcc= isSmaller(Account(100.0),Account(200.0),[](const Account& fir, const 
31   std::cout << "isSmaller(Account(100.0),Account(200.0)): " << resAcc << std::endl;
32
33   bool acc= isSmaller(std::string("3.14"),std::string("2.14"),[](const std::string& 
34   std::cout << "isSmaller(std::string(3.14),std::string(2.14)): " << acc << std::end
35
36   std::cout << std::endl;
37 }

Output 2.65s

isSmaller(3,4): true

isSmaller(2.14,3.14): true

isSmaller(std::string(abc),std::string(def)): true

isSmaller(Account(100.0),Account(200.0)): true

isSmaller(std::string(3.14),std::string(2.14)): false

Explanation#

https://www.educative.io/courses/generic-templates-in-cpp/m20Mg8J806A 4/10
3/20/22, 8:01 PM - Examples - Generic Programming Templates in C++

In the first example, we have passed only the built-in data types. In this
example, we have used the built-in types int , double , std::string , and an
Account class in lines 26 – 28. The function template isSmaller is
parametrized by a second template parameter, which defines the
comparison criterion. The default for the comparison is the predefined
function object std::less . A function object is a class for which the call
operator ( operator () ) is overloaded. This means that instances of function
objects behave similarly as a function. The Account class doesn’t support the
< operator. Thanks to the second template parameter, a lambda expression
like in lines 30 and 33 can be used. This means Account can be compared by
their balance and strings by their number. stod converts a string to a
double.

Since C++17, the constructor of a class template can deduce its arguments.
Study the first example of Class template argument deduction
(https://en.cppreference.com/w/cpp/language/class_template_argument_ded
uction) for a deeper understanding.

Example 3: Function Template


Argument Deduction by Reference#
1 // functionTemplateArgumentDeductionReference.cpp
2
3 template <typename T>
4 void func(T& param){}
5
6 template <typename T>
7 void constFunc(const T& param){}
8
9 int main(){
10   
11   int x = 2011;
12 const int cx = x;
https://www.educative.io/courses/generic-templates-in-cpp/m20Mg8J806A 5/10
3/20/22, 8:01 PM - Examples - Generic Programming Templates in C++
12   const int cx = x;
13   const int& rx = x;
14   
15   func(x);
16   func(cx);
17   func(rx);
18    
19   constFunc(x);
20   constFunc(cx);
21   constFunc(rx); 
22 }

Succeeded

Explanation#
In the above example, we have created two functions func and constFunc in
lines 4 and 7. Both of these functions accept parameters by reference (19 –
21).

For better understanding, click here (https://cppinsights.io/lnk?


code=dGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnZvaWQgZnVuYyhUJiBwYXJhbSl
7fQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnZvaWQgY29uc3RGdW5jKGNvb
nN0IFQmIHBhcmFtKXt9CgppbnQgbWFpbigpewogIAogIGludCB4ID0gMjAxM
TsKICBjb25zdCBpbnQgY3ggPSB4OwogIGNvbnN0IGludCYgcnggPSB4OwogIAo
gIGZ1bmMoeCk7CiAgZnVuYyhjeCk7CiAgZnVuYyhyeCk7CiAgIAogIGNvbnN0R
nVuYyh4KTsKICBjb25zdEZ1bmMoY3gpOwogIGNvbnN0RnVuYyhyeCk7IAp9
&insightsOptions=cpp17&std=cpp17&rev=1.0) to analyze the process using
C++ Insight.

https://www.educative.io/courses/generic-templates-in-cpp/m20Mg8J806A 6/10
3/20/22, 8:01 PM - Examples - Generic Programming Templates in C++

Example 4: Function Template


Argument Deduction by Universal
Reference#
1 // functionTemplateArgumentDeductionUniversalReference.cpp
2
3 template <typename T>
4 void funcUniversal(T&& param){}
5
6
7 int main(){
8   
9   int x = 2011;
10   const int cx = x;
11   const int& rx = x;
12   
13   funcUniversal(x);
14   funcUniversal(cx);
15   funcUniversal(rx);
16   funcUniversal(2014); 
17 }

Succeeded

Explanation#
In the above code, we have defined a function funcUniversal in line 4 which
accepts its parameters with a universal reference.
https://www.educative.io/courses/generic-templates-in-cpp/m20Mg8J806A 7/10
3/20/22, 8:01 PM - Examples - Generic Programming Templates in C++

For better understanding click here (https://cppinsights.io/lnk?


code=dGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnZvaWQgZnVuY1VuaXZlcnNhbC
hUJiYgcGFyYW0pe30KCgppbnQgbWFpbigpewogIAogIGludCB4ID0gMjAxMTs
KICBjb25zdCBpbnQgY3ggPSB4OwogIGNvbnN0IGludCYgcnggPSB4OwogIAogI
GZ1bmNVbml2ZXJzYWwoeCk7CiAgZnVuY1VuaXZlcnNhbChjeCk7CiAgZnVuY
1VuaXZlcnNhbChyeCk7CiAgZnVuY1VuaXZlcnNhbCgyMDE0KTsgCn0=&insigh
tsOptions=cpp17&std=cpp17&rev=1.0) to analyze the process using C++
Insight.

Example 5: Function Template


Argument Deduction by Value#
1 // functionTemplateArgumentDeductionValue.cpp
2
3 template <typename T>
4 void funcValue(T param){}
5
6 int main(){
7   
8   int x = 2011;
9   const int cx = x;
10   const int& rx = x;
11   
12   funcValue(x);
13   funcValue(cx);
14   funcValue(rx); 
15 }

Succeeded

https://www.educative.io/courses/generic-templates-in-cpp/m20Mg8J806A 8/10
3/20/22, 8:01 PM - Examples - Generic Programming Templates in C++

Explanation#
In the above example, we have implemented a function funcValue in line 4
which takes its parameter by value.

For better understanding click here (https://cppinsights.io/lnk?


code=dGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnZvaWQgZnVuY1ZhbHVlKFQgcG
FyYW0pe30KCmludCBtYWluKCl7CiAgCiAgaW50IHggPSAyMDExOwogIGNvb
nN0IGludCBjeCA9IHg7CiAgY29uc3QgaW50JiByeCA9IHg7CiAgCiAgZnVuY1Zh
bHVlKHgpOwogIGZ1bmNWYWx1ZShjeCk7CiAgZnVuY1ZhbHVlKHJ4KTsgCn0
=&insightsOptions=cpp17&std=cpp17&rev=1.0) to analyze the process using
C++ Insight.

Let’s solve an exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Template Arguments - Exercise

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/m20Mg8J806A 9/10
3/20/22, 8:01 PM - Examples - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/m20Mg8J806A 10/10
3/20/22, 8:02 PM - Exercise - Generic Programming Templates in C++

- Exercise
In this lesson, we'll solve an exercise on template arguments.

We'll cover the following

• Problem Statement

Problem Statement#
The class Matrix holds its values in the container Cont .

Cont should have a default argument std::vector .

Instantiate myIntVec and myDoubleVec without specifying the container


explicitly.

1 #include <initializer_list>
2 #include <iostream>
3 #include <list>
4 #include <vector>
5
6 template <typename T, template <typename, typename> class Cont >
7 class Matrix{
8 public:
9   explicit Matrix(std::initializer_list<T> inList): data(inList){
10     for (auto d: data) std::cout << d << " ";
11   }
12   int getSize() const{
13     return data.size();
14   }
15
16 private:
17   Cont<T, std::allocator<T>> data;
18
19 };
https://www.educative.io/courses/generic-templates-in-cpp/NE5gyo1VZ3m 1/3
3/20/22, 8:02 PM - Exercise - Generic Programming Templates in C++

20
21 int main(){
22
23   std::cout << std::endl;
24
25   // Define myIntVec and myDoubleVec with specifying containers explicitly
26   // Call getSize() function on it to check the result
27 (/learn)
28   Matrix<std::string,std::list> myStringList{"one", "two", "three", "four"};
29   std::cout << std::endl;
30   std::cout << "myStringList.getSize(): " << myStringList.getSize() << std::endl;
31
32   std::cout << std::endl;
33
34 }

Output 1.57s

one two three four

myStringList.getSize(): 4

We’ll look at the solution of this problem in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

https://www.educative.io/courses/generic-templates-in-cpp/NE5gyo1VZ3m 2/3
3/20/22, 8:02 PM - Exercise - Generic Programming Templates in C++

Back Next

- Examples - Solution

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/NE5gyo1VZ3m 3/3
3/20/22, 8:03 PM - Solution - Generic Programming Templates in C++

- Solution
Let's review the solution of the exercise in this lesson.

We'll cover the following

• Solution Review

• Explanation

Solution Review#
1 // templateClassTemplateMethods3.cpp
2
3 #include <initializer_list>
4 #include <iostream>
5 #include <list>
6 #include <vector>
7
8 template <typename T, template <typename, typename> class Cont = std::vector>
9 class Matrix{
10 public:
11   explicit Matrix(std::initializer_list<T> inList): data(inList){
12     for (auto d: data) std::cout << d << " ";
13   }
14   int getSize() const{
15     return data.size();
16   }
17
18 private:
19   Cont<T, std::allocator<T>> data;
20
21 };
22
23 int main(){
24
25   std::cout << std::endl;
26
https://www.educative.io/courses/generic-templates-in-cpp/3j28jxWmYGQ 1/3
3/20/22, 8:03 PM - Solution - Generic Programming Templates in C++
27   Matrix<int> myIntVec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
28   std::cout << std::endl;
29   std::cout << "myIntVec.getSize(): " << myIntVec.getSize() << std::endl;
30
31   std::cout << std::endl;
(/learn)
32
33   Matrix<double> myDoubleVec{1.1, 2.2, 3.3, 4.4, 5.5};
34   std::cout << std::endl;
35   std::cout << "myDoubleVec.getSize(): "  << myDoubleVec.getSize() << std::endl;
36
37   std::cout << std::endl;
38
39   Matrix<std::string,std::list> myStringList{"one", "two", "three", "four"};
40   std::cout << std::endl;
41   std::cout << "myStringList.getSize(): " << myStringList.getSize() << std::endl;
42
43   std::cout << std::endl;
44 }

Output 4.07s

1 2 3 4 5 6 7 8 9 10

myIntVec.getSize(): 10

1.1 2.2 3.3 4.4 5.5

myDoubleVec.getSize(): 5

one two three four

myStringList.getSize(): 4

Explanation#
The class template Matrix uses, by default, an std::vector for holding it’s
elements (line 8). Thanks to the default container, a Matrix can be
instantiated (lines 27 and 33) without explicitly specifying a container.

https://www.educative.io/courses/generic-templates-in-cpp/3j28jxWmYGQ 2/3
3/20/22, 8:03 PM - Solution - Generic Programming Templates in C++

Let’s move on to specialization in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise Specialization

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/3j28jxWmYGQ 3/3
3/20/22, 5:41 PM Specialization - Generic Programming Templates in C++

Specialization
Let's learn about template specialization in this lesson.

We'll cover the following

• Specialization

• Primary Template
• Partial Specialization

• Rules for Partial Specializations:


• Rules for Right Specialization:

• Full Specialization

Specialization#
Template specialization addresses the need to have different code for
different template argument types. Templates define the behavior of
families of classes and functions.

Often it is necessary that special types, non-types, or templates as


arguments are treated as special.

You can fully specialize templates; class templates can even be partially
specialized.
The methods and attributes of specialization don’t have to be identical.
General or Primary templates can coexist with partially or fully
specialized templates.

https://www.educative.io/courses/generic-templates-in-cpp/g758AwL0jQj 1/5
3/20/22, 5:41 PM Specialization - Generic Programming Templates in C++

The compiler prefers fully specialized to partially specialized templates


and partially specialized templates to primary templates.

Primary Template#
The primary template has to be declared before the partially or fully
specialized templates.

If the primary template is not needed, just a declaration will suffice.

template <typename T, int Line, int Column> class Matrix;

template <typename T>

class Matrix<T, 3, 3>{};

template <>class Matrix<int, 3, 3>{};

Partial Specialization#
The partial specialization of a template is only supported for class templates
and it has template arguments and template parameters.

1 template <typename T, int Line, int Column> class Matrix{};
2
3 template <typename T>
4 class Matrix<T, 3, 3>{};
5
6 template <int Line, int Column>
7 class Matrix<double, Line, Column>{};
8
9 Matrix<int, 3, 3> m1; // class Matrix<T, 3, 3> 
10 Matrix<double, 10, 10> m2; // class Matrix<double, Line, Column> 
https://www.educative.io/courses/generic-templates-in-cpp/g758AwL0jQj 2/5
3/20/22, 5:41 PM Specialization - Generic Programming Templates in C++
11 Matrix<std::string, 4, 3> m3;  // class Matrix<T, Line, Column>

(/learn)

Rules for Partial Specializations:#


1. The compiler uses a partial specialization if the parameters of the class
are a subset of the template arguments.

2. The template parameters which are not specified must be given as


template arguments, for example, lines 3 and 4 in the code snippet.

3. The number and sequence of the template arguments must match with
the number and sequence of the template parameters of the primary
template.

4. If you use defaults for template parameters, you don’t have to provide
the template arguments. Only the primary template accepts defaults.

Rules for Right Specialization:#


Three rules for getting the right specialization:

1. If the compiler finds only one specialization, it uses that specialization.

2. If the compiler finds more than one specialization, it uses the most
specialized one.
If the compiler can’t find the most specialized one, it
throws an error.

3. If the compiler finds no specialization, it simply uses the primary


template.

Template A is more specialized than template B if:

B can accept all arguments that A can accept.

B can accept arguments that A cannot accept.

To learn more about partial specialization, click here


https://www.educative.io/courses/generic-templates-in-cpp/g758AwL0jQj 3/5
3/20/22, 5:41 PM Specialization - Generic Programming Templates in C++

(https://en.cppreference.com/w/cpp/language/partial_specialization).

Full Specialization#
For a fully specialized template, you have to provide all template arguments
for the template parameters. The number of template parameters is reduced
to an empty list.

1 template <typename T> struct Type{
2 std::string getName() const {
3     return "unknown";
4     };
5 };
6 template <>
7 struct Type<Account>{
8     std::string getName() const {
9     return "Account";
10 };

If you define the methods of a class template outside of the class, you have to
specify the template arguments in angle brackets after the name of the class.
Define the method of a fully specialized class template outside the class body
without the empty template parameter list: template <> .

template <typename T, int Line, int Column>

struct Matrix;

template <>

struct Matrix<int, 3, 3>{

int numberOfElements() const;

};

// template <>

int Matrix<int, 3, 3>::numberOfElements() const {

return 3 * 3;

};

To learn more about full specialization, click here


https://www.educative.io/courses/generic-templates-in-cpp/g758AwL0jQj 4/5
3/20/22, 5:41 PM Specialization - Generic Programming Templates in C++

(https://en.cppreference.com/w/cpp/language/template_specialization).

In the next lesson, we’ll look at a few examples of template specialization.

Back Next

- Solution - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/g758AwL0jQj 5/5
3/20/22, 8:04 PM - Examples - Generic Programming Templates in C++

- Examples
In this lesson, we'll look at a few examples of template specialization.

We'll cover the following

• Example 1: Template Specialization

• Explanation
• Example 2: Template Specialization External

• Explanation
• Example 3: Template Specialization Full

• Explanation

• Example 4: Template Specialization Type Traits


• Explanation
• Example 5: Template Types
• Explanation

Example 1: Template Specialization#


1 // TemplateSpecialization.cpp
2
3 #include <iostream>
4
5 class Account{
6 public:
7   explicit Account(double b): balance(b){}
8   double getBalance() const {
9     return balance;
10   }
11 private:
https://www.educative.io/courses/generic-templates-in-cpp/mE0mkoNgogA 1/10
3/20/22, 8:04 PM - Examples - Generic Programming Templates in C++

12   double balance;
13 };
14
15 template <typename T, int Line, int Column>
16 class Matrix{
17   std::string getName() const { return "Primary Template"; }
18 };
19
20 template <typename T>
21 class Matrix<T,3,3>{
22   std::string name{"Partial Specialization"};
23 };
24
25 template <>
26 class Matrix<int,3,3>{};
27
28
29 template<typename T>
30 bool isSmaller(T fir, T sec){
31   return fir < sec;
32 }
33
34 template <>
35 bool isSmaller<Account>(Account fir, Account sec){
36   return fir.getBalance() < sec.getBalance();
37 }
38
39 int main(){
40
41   std::cout << std::boolalpha << std::endl;
42
43   Matrix<double,3,4> primaryM;
44   Matrix<double,3,3> partialM;
45   Matrix<int,3,3> fullM;
46
47   std::cout << "isSmaller(3,4): "  << isSmaller(3,4) << std::endl;
48   std::cout << "isSmaller(Account(100.0),Account(200.0)): "<< isSmaller(Account(100.
49
50   std::cout << std::endl;
51
52 }
53

Output 1.67s

https://www.educative.io/courses/generic-templates-in-cpp/mE0mkoNgogA 2/10
3/20/22, 8:04 PM - Examples - Generic Programming Templates in C++

isSmaller(3,4): true

isSmaller(Account(100.0),Account(200.0)): true

Explanation#
In the above example, we’re modifying the codes that we have used in the
previous lesson
(https://www.educative.io/collection/page/10370001/5799373671759872/6213
754565951488/#primary-template).

Primary template is called when we use values other than


Matrix<data_type, 3, 3> (line 43).

Partial specialization is called when we instantiate Matrix<data_type,


3, 3> where data_type is not int (line 44).

Full specialization is called when we explicitly use int as a data type:


Matrix<int, 3, 3> (line 45)

Full specialization of the function template isSmaller is only applicable


for Account objects. This allows it to compare two Account objects
based on their balance (line 48).

Example 2: Template Specialization


External#
1 //TemplateSpecializationExternal.cpp 
2
3 #include <iostream>
4
5
6 template <typename T=std::string, int Line=10, int Column=Line>
7 class Matrix{
8 public:
9   int numberOfElements() const;
10 };
https://www.educative.io/courses/generic-templates-in-cpp/mE0mkoNgogA 3/10
3/20/22, 8:04 PM - Examples - Generic Programming Templates in C++
10 };
11
12 template <typename T, int Line, int Column>
13 int Matrix<T,Line,Column>::numberOfElements() const {
14   return Line * Column;
15 }
16
17
18 template <typename T>
19 class Matrix<T,3,3>{
20 public:
21   int numberOfElements() const;
22 };
23
24 template <typename T>
25 int Matrix<T,3,3>::numberOfElements() const {
26   return 3*3;
27 }
28
29
30 template <>
31 class Matrix<int,3,3>{
32 public:
33   int numberOfElements() const;
34 };
35
36 int Matrix<int,3,3>::numberOfElements() const {
37   return 3*3;
38 }
39
40 int main(){
41
42   std::cout << std::endl;
43
44   Matrix<double,10,5> matBigDouble;
45   std::cout << "matBigDouble.numberOfElements(): " << matBigDouble.numberOfElements(
46
47   // Matrix matString;    // ERROR
48   Matrix<> matString;
49   std::cout << "matString.numberOfElements(): " << matString.numberOfElements() << s
50
51   Matrix<float> matFloat;
52   std::cout << "matFloat.numberOfElements(): " << matFloat.numberOfElements() << std
53
54   Matrix<bool,20> matBool;
55   std::cout << "matBool.numberOfElements(): " << matBool.numberOfElements() << std::
56
57   Matrix <double,3,3> matSmallDouble;
58   std::cout << "matSmallDouble.numberOfElements(): " << matSmallDouble.numberOfEleme
59
60   Matrix <int,3,3> matInt;
61   std::cout << "matInt.numberOfElements(): " << matInt.numberOfElements() << std::en
https://www.educative.io/courses/generic-templates-in-cpp/mE0mkoNgogA 4/10
3/20/22, 8:04 PM - Examples - Generic Programming Templates in C++

62
63   std::cout << std::endl;
64
65 }
66

Output 1.38s

matBigDouble.numberOfElements(): 50

matString.numberOfElements(): 100
matFloat.numberOfElements(): 100

matBool.numberOfElements(): 400

matSmallDouble.numberOfElements(): 9

matInt.numberOfElements(): 9

Explanation#
In the above example, we have set the default value of line to 10 (line 6)
and used the value for line as the default for column . The method
numberOfElements returns the product of both numbers as a result. If we call
the Matrix with arguments, then these passed arguments override the
default. For float and string , it returns the 100 as no arguments are passed
and the default arguments are used (lines 48 and 51).

Example 3: Template Specialization


Full#
1 // templateSpecializationFull.cpp
2
3 #include <iostream>
https://www.educative.io/courses/generic-templates-in-cpp/mE0mkoNgogA 5/10
3/20/22, 8:04 PM - Examples - Generic Programming Templates in C++
3 #include <iostream>
4 #include <string>
5
6 template <typename T>
7 T min(T fir, T sec){
8   return (fir < sec) ? fir : sec;
9 }
10
11 template <>
12 bool min<bool>(bool fir, bool sec){
13   return fir & sec;
14 }
15
16 int main(){
17
18   std::cout << std::boolalpha << std::endl;
19
20   std::cout << "min(3.5, 4.5): "  << min(3.5, 4.5) << std::endl;
21   std::cout << "min<double>(3.5, 4.5): "  << min<double>(3.5, 4.5) << std::endl;
22
23   std::cout << "min(true, false): "  << min(true, false) << std::endl;
24   std::cout << "min<bool>(true, false): "  << min<bool>(true, false) << std::endl;
25
26   std::cout << std::endl;
27
28 }
29

Output 1.52s

min(3.5, 4.5): 3.5

min<double>(3.5, 4.5): 3.5

min(true, false): false

min<bool>(true, false): false

Explanation#

https://www.educative.io/courses/generic-templates-in-cpp/mE0mkoNgogA 6/10
3/20/22, 8:04 PM - Examples - Generic Programming Templates in C++

In the above example, we have defined a full specialization for bool . The
primary and the full specialization are implicitly invoked in the lines (20 and
23) and explicitly invoked in the lines (21 and 24).

Example 4: Template Specialization


Type Traits#
1 // templateSpecializationTypeTraits.cpp
2
3 #include <iostream>
4 #include <type_traits>
5
6 using namespace std;
7
8 template <typename T>
9 void getPrimaryTypeCategory(){
10
11   cout << boolalpha << endl;
12
13   cout << "is_void<T>::value: " << is_void<T>::value << endl;
14   cout << "is_integral<T>::value: " << is_integral<T>::value << endl;
15   cout << "is_floating_point<T>::value: " << is_floating_point<T>::value << endl;
16   cout << "is_array<T>::value: " << is_array<T>::value << endl;
17   cout << "is_pointer<T>::value: " << is_pointer<T>::value << endl;
18   cout << "is_reference<T>::value: " << is_reference<T>::value << endl;
19   cout << "is_member_object_pointer<T>::value: " << is_member_object_pointer<T>::val
20   cout << "is_member_function_pointer<T>::value: " << is_member_function_pointer<T>:
21   cout << "is_enum<T>::value: " << is_enum<T>::value << endl;
22   cout << "is_union<T>::value: " << is_union<T>::value << endl;
23   cout << "is_class<T>::value: " << is_class<T>::value << endl;
24   cout << "is_function<T>::value: " << is_function<T>::value << endl;
25   cout << "is_lvalue_reference<T>::value: " << is_lvalue_reference<T>::value << endl
26   cout << "is_rvalue_reference<T>::value: " << is_rvalue_reference<T>::value << endl
27
28   cout << endl;
29
30 }
31

https://www.educative.io/courses/generic-templates-in-cpp/mE0mkoNgogA 7/10
3/20/22, 8:04 PM - Examples - Generic Programming Templates in C++

Output 3.93s

is_void<T>::value: true

is_integral<T>::value: false

is_floating_point<T>::value: false

is_array<T>::value: false

is_pointer<T>::value: false

is_reference<T>::value: false

is_member_object_pointer<T>::value: false

is_member_function_pointer<T>::value: false

Explanation#
We have used the type_traits
(https://www.educative.io/collection/page/10370001/5799373671759872/6380
229176066048) library which detects at compile-time to which primary type
category void (line 13) belongs to. The primary type categories are complete
and exclusive. This means each type belongs exactly to one primary type
category. For example, void returns true for the type-trait std::is_void
and false
(/learn)for all the other type categories.

Example 5: Template Types#


1 // templateTypes.cpp
2
3 #include <iostream>
4 #include <string>
5
6 template<typename T>
7 struct Type{
8   std::string getName() const {
9     return "unknown";
10   }
11 };
12
13 int main(){
https://www.educative.io/courses/generic-templates-in-cpp/mE0mkoNgogA 8/10
3/20/22, 8:04 PM - Examples - Generic Programming Templates in C++
13 int main(){
14
15   std::cout << std::boolalpha << std::endl;
16
17   Type<float> tFloat;
18   std::cout << "tFloat.getName(): " << tFloat.getName() << std::endl;
19
20   std::cout << std::endl;
21
22 }
23

Output 1.39s

tFloat.getName(): unknown

Explanation#
In the above example, the method getName returns unknown for any type
passed in the argument of type function (line 8). If we specialize the class
template for further types, we will implement a type deduction system at
compile-time. We’ll look at it in the coming exercise.

We’ll solve an exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


https://www.educative.io/courses/generic-templates-in-cpp/mE0mkoNgogA 9/10
3/20/22, 8:04 PM - Examples - Generic Programming Templates in C++

you instead of you applying to them. See how


(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Specialization - Exercise

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/mE0mkoNgogA 10/10
3/20/22, 5:42 PM - Exercise - Generic Programming Templates in C++

(/learn)

- Exercise
Let's solve a template specialization problem in this lesson.

We'll cover the following

• Problem Statement

Problem Statement#
The class template Type in the code below returns to each type the name
unknown .

Use the class template Type as a starting point to write a type


introspection system with the help of partial and full specialization.

You need to write code for int , double , an arbitrary class named
Account , pointer , const , and string .

1 #include <iostream>
2 #include <string>
3
4 // Implement with full and partial specialization
5 // Write your code here
6
7 template<typename T>
8 struct Type{
9   std::string getName() const {
10     return "unknown";
11   }
12 };
13
14 int main(){
15
16   std::cout << std::boolalpha << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/qZq27KK1WgG 1/3
3/20/22, 5:42 PM - Exercise - Generic Programming Templates in C++
17
18   // call objects for each defined templetes here
19
20   // An example of float is given below which returns "unknown"
21   Type<float> tFloat;
22   std::cout << "tFloat.getName(): " << tFloat.getName() << std::endl;
23
24   std::cout << std::endl;
25
26 }

In the next lesson, we’ll look at the solution to this exercise.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Examples - Solution

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qZq27KK1WgG 2/3
3/20/22, 5:42 PM - Exercise - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/qZq27KK1WgG 3/3
3/20/22, 8:05 PM - Solution - Generic Programming Templates in C++

- Solution
Let's look at the solution review for the exercise we presented in the last lesson.

We'll cover the following

• Solution Review

• Explanation

Solution Review#
1 // Template Types
2
3 #include <iostream>
4 #include <string>
5
6 class Account{};
7
8 template<typename T>
9 struct Type{
10   std::string getName() const {
11     return "unknown";
12   }
13 };
14
15 template<typename T>
16 struct Type<T*>{
17   std::string getName() const {
18     return "pointer";
19   }
20 };
21
22 template<typename T>
23 struct Type<const T>{
24   std::string getName() const {
25     return "const";
26   }
https://www.educative.io/courses/generic-templates-in-cpp/x1mQqPOmE3q 1/4
3/20/22, 8:05 PM - Solution - Generic Programming Templates in C++

27 };
28
29
30 template<>
31 struct Type<int>{
32   std::string getName() const {
33     return "int";
34   }
35 };
36
37 template<>
38 struct Type<double>{
39   std::string getName() const {
40     return "double";
41   }
42 };
43
44 template<>
45 struct Type<std::string>{
46   std::string getName() const {
47     return "std::string";
48   }
49 };
50
51 template<>
52 struct Type<Account>{
53   std::string getName() const {
54     return "Account";
55   }
56 };
57
58 int main(){
59
60   std::cout << std::boolalpha << std::endl;
61
62   Type<float> tFloat;
63   std::cout << "tFloat.getName(): " << tFloat.getName() << std::endl;
64   
65   Type<const float> tConstFloat;
66   std::cout << "tConstFloat.getName(): " << tConstFloat.getName() << std::endl;
67    
68   Type<float*> tFloatPointer;
69   std::cout << "tFloatPointer.getName(): " << tFloatPointer.getName() << std::endl;
70    
71   Type<double> tDouble;
72   std::cout << "tDouble.getName(): " << tDouble.getName() << std::endl;
73
74   Type<std::string> tString;
75   std::cout << "tString.getName(): " << tString.getName() << std::endl;
76
77   Type<int> tInt;
78 std::cout << "tInt.getName(): " << tInt.getName() << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/x1mQqPOmE3q 2/4
3/20/22, 8:05 PM - Solution - Generic Programming Templates in C++
78   std::cout <<  tInt.getName():   << tInt.getName() << std::endl;
79
80   Type<Account> tAccount;
81   std::cout << "tAccount.getName(): " << tAccount.getName() << std::endl;
82
83   std::cout << std::endl;
84
85 }
86

Output 1.31s

tFloat.getName(): unknown

tConstFloat.getName(): const

tFloatPointer.getName(): pointer

tDouble.getName(): double

tString.getName(): std::string

tInt.getName(): int

tAccount.getName(): Account

(/learn)

Explanation#
In the above code, we have separately defined
the partial and full
specialization of the class template Type . The partial and full specializations
accept an int , double , Account , string , const , and Pointer . On calling
each type, the relative type is returned. We have not defined the full
specialization for float , so when instantiating the class template for float ,
it gives an unknown in response.

We have covered the basics of templates in this chapter. In the next chapter,
we’ll learn about the details of templates. Let’s start with template
instantiation in the next lesson.
https://www.educative.io/courses/generic-templates-in-cpp/x1mQqPOmE3q 3/4
3/20/22, 8:05 PM - Solution - Generic Programming Templates in C++

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise Template Instantiation

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/x1mQqPOmE3q 4/4
3/20/22, 5:53 PM Template Instantiation - Generic Programming Templates in C++

(/learn)

Template Instantiation
In this lesson, we'll learn about template instantiation.

We'll cover the following

• Template Instantiation

• Implicit
• Explicit

• Lazy Evaluation

Template Instantiation#
Templates can be implicitly and explicitly instantiated. Implicit instantiation
means automatically and explicit means manually.

Implicit#
std::vector<int> vec{};

bool isSmaller<double>(fir, sec);

bool isSmaller(fir, sec);

Explicit#
template class std::vector<int>;
template bool std::vector<double>::empty() const;

template bool isSmaller<double>(double, double); 

template bool isSmaller(double, double);

https://www.educative.io/courses/generic-templates-in-cpp/B8A2jn0D4LJ 1/3
3/20/22, 5:53 PM Template Instantiation - Generic Programming Templates in C++

Lazy Evaluation#
When a class is instantiated, only the method declarations are available.

The definition of a method is only instantiated when it is used.

It is not necessary that all methods of class templates are valid for the
template arguments. You can only use the methods, which are valid for a
given instantiation.

In the next lesson, we’ll look at an example of template instantiation.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solution - Example

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/B8A2jn0D4LJ 2/3
3/20/22, 5:53 PM Template Instantiation - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/B8A2jn0D4LJ 3/3
3/20/22, 8:07 PM - Example - Generic Programming Templates in C++

- Example
Let's have a look at an example of template instantiation.

We'll cover the following

• Example: Template Instantiation

• Explanation

Example: Template Instantiation#


1 // templateInstantiation.cpp
2
3 #include <iostream>
4 #include <vector>
5
6 template <typename T, int N>
7 class Array{
8
9 public:
10   Array()= default;
11
12   int getSize() const{
13     return N;
14   }
15
16   std::vector<T> elem;
17 };
18
19 template<typename T>
20 bool isSmaller(T fir, T sec){
21   return fir < sec;
22 }
23
24 template class std::vector<int>;
25 template bool std::vector<double>::empty() const;
26
https://www.educative.io/courses/generic-templates-in-cpp/YQzNvWngvNM 1/4
3/20/22, 8:07 PM - Example - Generic Programming Templates in C++
27 template class Array<int, 20>;
28 template int Array<double, 5>::getSize() const;
29
30 template bool isSmaller(double, double);
31 template bool isSmaller<int>(int, int);
32
33 int main(){
34
35   std::cout << std::endl;
36   
37   std::cout << std::boolalpha << "implicit" << std::endl;
38   
39   std::cout << std::endl;
40   
41   std::vector<int> vec{};
42   std::cout << "vec.size(): " << vec.size() << std::endl;
43   
44   Array<int, 10> arr;
45   std::cout << "arr.getSize(): " << arr.getSize() << std::endl;
46   
47   std::cout << std::endl;
48   
49   std::cout << "isSmaller(5, 10): " << isSmaller(5,10) << std::endl;
50   
51   std::cout << "isSmaller<double>(5.5, 6.5): " << isSmaller<double>(5.5, 6.5) << std
52   
53   std::cout << std::endl;
54   
55 }
56

Output 1.89s

implicit

vec.size(): 0

arr.getSize(): 10

isSmaller(5, 10): true

isSmaller<double>(5.5, 6.5): true

https://www.educative.io/courses/generic-templates-in-cpp/YQzNvWngvNM 2/4
3/20/22, 8:07 PM - Example - Generic Programming Templates in C++

(/learn)

Explanation#
In the above example, we have implemented a template class Array which
includes a function getSize() that returns the size of the element N passed
into the constructor. We have also defined a template function isSmaller
bool and its return type is declared explicitly which returns true if the first
passed argument is less than the second argument.

Lines 24 – 31 contain explicit template instantiation. The main program


contains implicit template instantiation. Line 24 is an explicit instantiation
for int and line 25 is an explicit instantiation of the method getSize for
double . The lines 27 and 28 are quite similar for Array . The compiler can
automatically deduce the template argument for the function argument in
line 30.

In the next lesson, we’ll solve a small exercise on template instantiation.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Template Instantiation - Exercise

Completed

https://www.educative.io/courses/generic-templates-in-cpp/YQzNvWngvNM 3/4
3/20/22, 8:07 PM - Example - Generic Programming Templates in C++

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/YQzNvWngvNM 4/4
3/20/22, 5:54 PM - Exercise - Generic Programming Templates in C++

(/learn)

- Exercise
Let's solve an exercise in this lesson.

We'll cover the following

• Problem Statement

Problem Statement#
Define a class template with at least one method. This method should not be
valid for all possible template arguments. Instantiate the class template for
an invalid template argument.
What happens, when you

don’t instantiate?

implicitly instantiate?

or explicitly instantiate the method?

1 #include <iostream>
2
3 // Define a class template here with one method
4
5 int main() {
6   // call these methods here
7 }

In the next lesson, we’ll look at the solution for this exercise.
https://www.educative.io/courses/generic-templates-in-cpp/7AgkJ127Xyy 1/2
3/20/22, 5:54 PM - Exercise - Generic Programming Templates in C++

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Example - Solution

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/7AgkJ127Xyy 2/2
3/20/22, 5:54 PM - Solution - Generic Programming Templates in C++

- Solution
Let's have a look at the solution review of the last exercise.

We'll cover the following

• Solution Review

• Explanation

Solution Review#
1 // templateInstantiationInvalid.cpp
2
3 (/learn)
#include <iostream>
4 #include <vector>
5
6 template <int Nom, int Denom>
7 class Rational{
8 public:
9     int getFloor(){
10         return Nom / Denom; 
11     }
12 };
13     
14 // template int Rational<5, 0>::getFloor();
15
16 int main(){
17
18   std::cout << std::endl;
19   
20   Rational<5, 3> rat1;
21   std::cout << "rat1.getFloor(): " << rat1.getFloor() << std::endl;
22
23
24   Rational<5, 0> rat2;
25   // std::cout << "rat2.getFloor(): " << rat2.getFloor() << std::endl;
26   
https://www.educative.io/courses/generic-templates-in-cpp/JQRnWgvjQgD 1/3
3/20/22, 5:54 PM - Solution - Generic Programming Templates in C++

27   std::cout << std::endl;
28   
29 }
30

Explanation#
In the above code, we have called the getFloor function for 5 and 3 in line 9,
and it returns 1. To invoke the function for an invalid call, we can give the
arguments 5 and 0 which gives an error.

In the next lesson, we’ll discuss variadic templates.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise Variadic Templates

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/JQRnWgvjQgD 2/3
3/20/22, 5:54 PM - Solution - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/JQRnWgvjQgD 3/3
3/20/22, 5:55 PM Variadic Templates - Generic Programming Templates in C++

Variadic Templates
Let's learn about variadic templates in detail in this lesson.

We'll cover the following

• Variadic Templates

• Parameter Pack

Variadic Templates#
A variadic template is a template that can has an arbitrary number of
parameters.

template <typename ... Args>

void variadicTemplate(Args ... args){ . . . . }

Parameter Pack#
A template parameter pack is a template parameter that accepts zero or
more template arguments (non-types, types, or templates). A function
parameter pack is a function parameter that accepts zero or more function
arguments.
(/learn)
By using the ellipse (…), Args- or args becomes a parameter pack.
Args is a template parameter pack; args is a function parameter pack.

Parameter packs can only be packed and unpacked.


If the ellipsis is left from Args , the parameter pack will be packed and if
https://www.educative.io/courses/generic-templates-in-cpp/B6qkMM2LjKx 1/3
3/20/22, 5:55 PM Variadic Templates - Generic Programming Templates in C++

the ellipse is right from Args , the parameter pack will be unpacked.

The compiler can automatically deduce the template arguments in case


of a function template.

For example, the following classes/functions in STL extensively use variadic


templates.
Variadic Templates are often used in the Standard Template
Library:

sizeof -Operator, std::tuple , std::thread , std::make_unique , std::lock

The usage of parameter packs obeys a typical pattern for class templates.

Perform an operation on the first element of the parameter pack and


recursively invoke the operation on the remaining elements.
The recursion ends after a finite number of steps.
The boundary condition is typically a fully specialized template.

1 template<>
2 struct Mult<>{ .... }
3 template<int i, int ... tail >
4 struct Mult<i, tail ...>{ ....

To learn more about variadic templates, click here


(https://en.cppreference.com/w/cpp/language/parameter_pack).

In the next lesson, we’ll study examples of variadic templates.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
d i &
https://www.educative.io/courses/generic-templates-in-cpp/B6qkMM2LjKx di & i M h 20222/3
3/20/22, 5:55 PM Variadic Templates - Generic Programming Templates in C++

utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solution - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/B6qkMM2LjKx 3/3
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++

(/learn)

- Examples
Let's look at the examples of variadic templates.

We'll cover the following

• Example 1: Variadic Template

• Explanation
• Example 2: Template Perfect Forwarding

• Explanation

Example 1: Variadic Template#


1 // templateVariadicTemplates.cpp
2
3 #include <iostream>
4
5 template <typename... Args>
6 int printSize(Args... args){
7   return sizeof ...(args);
8 }
9
10 template<int ...>
11 struct Mult;
12
13 template<>
14 struct Mult<>{
15   static const int value= 1;
16 };
17
18 template<int i, int ... tail>
19 struct Mult<i, tail ...>{
20   static const int value= i * Mult<tail ...>::value;
21 };
22
23 int main(){
https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 1/6
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++
23 int main(){
24
25   std::cout << std::endl;
26
27   std::cout << "printSize(): " << printSize() << std::endl;
28   std::cout << "printSize(template,2011,true): " << printSize("template",2011,true) 
29   std::cout << "printSize(1, 2.5, 4, 5, 10): " <<  printSize(1, 2.5, 4, 5, 10) << st
30
31   std::cout << std::endl;

Explanation#
In the above example, we have used printSize function, which prints the
number of elements (of any type) passed as arguments. It detects the
number of elements on compile-time using the sizeof operator, and in case
of an empty argument list, it returns 0.

There is a struct defined as Mult which takes arguments of integer type


and return their product. If there is no argument passed, then it returns 1
which is the neutral element for multiplication. The result is stored in the
value in the fully specialized template in lines 13 – 16. The partial
specialization in lines 18 – 21 starts the recursion, which ends with the
aforementioned fully specialization for 0. The primary template in line 10 is
never used and must, therefore, never be defined.

To visualize the template instantiation for the above-mentioned example


click here (https://cppinsights.io/lnk?
code=I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHR5cGVuYW1lLi4uI
EFyZ3M+CmludCBwcmludFNpemUoQXJncy4uLiBhcmdzKXsKICByZXR1cm4g
c2l6ZW9mIC4uLihhcmdzKTsKfQoKdGVtcGxhdGU8aW50IC4uLj4Kc3RydWN0
IE11bHQ7Cgp0ZW1wbGF0ZTw+CnN0cnVjdCBNdWx0PD57CiAgc3RhdGljIGN
vbnN0IGludCB2YWx1ZT0gMTsKfTsKCnRlbXBsYXRlPGludCBpLCBpbnQgLi4u
IHRhaWw+CnN0cnVjdCBNdWx0PGksIHRhaWwgLi4uPnsKICBzdGF0aWMgY
29uc3QgaW50IHZhbHVlPSBpICogTXVsdDx0YWlsIC4uLj46OnZhbHVlOwp9O
woKaW50IG1haW4oKXsKCiAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbDsKCiAgc
https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 2/6
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++

3RkOjpjb3V0IDw8ICJwcmludFNpemUoKTogIiA8PCBwcmludFNpemUoKSA8P

CBzdGQ6OmVuZGw7CiAgc3RkOjpjb3V0IDw8ICJwcmludFNpemUodGVtcGxh
dGUsMjAxMSx0cnVlKTogIiA8PCBwcmludFNpemUoInRlbXBsYXRlIiwyMDEx
LHRydWUpIDw8IHN0ZDo6ZW5kbDsKICBzdGQ6OmNvdXQgPDwgInByaW50
U2l6ZSgxLCAyLjUsIDQsIDUsIDEwKTogIiA8PCAgcHJpbnRTaXplKDEsIDIuNSw
gNCwgNSwgMTApIDw8IHN0ZDo6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8IHN0ZD
o6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8ICJNdWx0PDEwPjo6dmFsdWU6ICIgPD
wgTXVsdDwxMD46OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKICBzdGQ6OmNvdX
QgPDwgIk11bHQ8MTAsMTAsMTA+Ojp2YWx1ZTogIiA8PCBNdWx0PDEwLDE
wLDEwPjo6dmFsdWUgPDwgc3RkOjplbmRsOwogIHN0ZDo6Y291dCA8PCAiT
XVsdDwxLDIsMyw0LDU+Ojp2YWx1ZTogIiA8PCBNdWx0PDEsMiwzLDQsNT4
6OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW
5kbDsKCn0K&insightsOptions=cpp17&std=cpp17&rev=1.0).

Example 2: Template Perfect


Forwarding#

https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 3/6
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++

// templatePerfectForwarding.cpp

#include <iostream>

#include <utility>

template<typename T, typename ... Args>

T createT(Args&& ... args){

return T(std::forward<Args>(args) ...);

struct MyStruct{

MyStruct(int&, double&, double&&){}

friend std::ostream& operator<< (std::ostream& out, const MyStruct&){

out << "MyStruct" << std::endl;

return out;
}

};

int main(){

std::cout << std::endl;

double myDouble= createT<double>();

std::cout << "myDouble: " << myDouble << std::endl;

int myInt= createT<int>(1);

std::cout << "myInt: " << myInt << std::endl;

std::string myString= createT<std::string>("My String");

std::cout << "myString: " << myString << std::endl;

MyStruct myStruct= createT<MyStruct>(myInt, myDouble, 3.14);

std::cout << "myStruct: " << myStruct << std::endl;

std::cout << std::endl;

Explanation#
In the above example, we have created a createT function which invokes
the constructor T with the arguments args . If there is no value passed, it
invokes the default constructor. The magic of the factory function createT is
https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 4/6
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++
g y
that it can invoke each constructor. Thanks to perfect forwarding, each

value can be used such as an lvalue or an rvalue; thanks to parameter packs,


any number of arguments can be used. In the case of MyStruct , a
constructor that requires three arguments is used.

The pattern of the function template createT is exactly the pattern, factory
functions such as std::make_unique , std::make_shared , std::make_pair , or
std::make_tuple use.

In the next lesson, we’ll solve exercises related to variadic templates.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Variadic Templates - Exercises

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 5/6
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 6/6
3/20/22, 5:56 PM - Exercises - Generic Programming Templates in C++

(/learn)

- Exercises
Let's solve a couple of exercises to test your understanding of variadic templates.

We'll cover the following

• Try It Out!

• Problem Statement 2

Try It Out!#
The function createT in the Example 2
(https://www.educative.io/collection/page/10370001/5799373671759872/6297
046497624064#example-2-template-perfect-forwarding)
is the perfect factory
function because it can invoke each constructor. Try to find a constructor
call, which cannot be used in the function template createT .

1 #include <iostream>
2 #include <utility>
3
4 template<typename T, typename ... Args>
5 T createT(Args&& ... args){
6   return T(std::forward<Args>(args) ...);
7 }
8
9 // Try to break the code
10
11 struct MyStruct{
12   MyStruct(int&, double&, double&&){}
13   friend std::ostream& operator<< (std::ostream& out, const MyStruct&){
14       out << "MyStruct" << std::endl;
15       return out;
16   }
17 };
https://www.educative.io/courses/generic-templates-in-cpp/JQKyvqxRnnJ 1/3
3/20/22, 5:56 PM - Exercises - Generic Programming Templates in C++
17 };
18
19 int main(){
20
21   // Call it here after breaking the code
22
23   std::cout << std::endl;
24 }

Problem Statement 2#
A typical example of a variadic template is the C function printf . Try to
implement it with variadic templates.

1 #include <iostream>
2  
3 void myPrintf(const char* format) {
4     std::cout << format;
5 }
6  
7 template<typename T, typename... Args>
8 void myPrintf(const char* format, T value, Args... args){
9     // Implement the function here
10 }
11  
12 int main(){
13   // the given line should print "Hello world! 2011"
14   myPrintf("% world% %\n","Hello",'!',2011);
15 }
16

https://www.educative.io/courses/generic-templates-in-cpp/JQKyvqxRnnJ 2/3
3/20/22, 5:56 PM - Exercises - Generic Programming Templates in C++

In the next lesson, we’ll look at the solution of problem statement 2.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Examples - Solution

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/JQKyvqxRnnJ 3/3
3/20/22, 5:58 PM - Solution - Generic Programming Templates in C++

(/learn)

- Solution
In this lesson, we'll look at the solution review of the problem statement 2 form last exercise.

We'll cover the following

• Solution Review of Problem Statement 2

• Explanation

Solution Review of Problem


Statement 2#
1 // printf.cpp
2
3 #include <iostream>
4  
5 void myPrintf(const char* format) 
6 {
7     std::cout << format;
8 }
9  
10 template<typename T, typename... Args>
11 void myPrintf(const char* format, T value, Args... args)
12 {
13 ····for·(·;·*format·!=·'\0';·format++·)·{
14         if ( *format == '%' ) {
15            std::cout << value;
16            myPrintf(format+1, args...);
17            return;
18         }
19         std::cout << *format;
20     }
21 }
22  
23 int main(){
24 P i tf("% ld% %\ " "H ll " '!' 2011)
https://www.educative.io/courses/generic-templates-in-cpp/qAK1PwqXKGp 1/3
3/20/22, 5:58 PM - Solution - Generic Programming Templates in C++
24     myPrintf("% world% %\n","Hello",'!',2011);
25 }
26

Output 1.58s

Hello world! 2011

Explanation#
The printf function uses variadic templates to implement a type-safe
printf variant. The format string is specified and thanks to function
template argument deduction, the compiler deduces the types.

The function templates loops (line 13) as long as the format symbol is not
equal to \0 . When the format symbol is not equal to \0 , two control flows
are possible. First, if the format starts with % (line 14), the first argument
value is displayed, and myPrintf is invoked once more but with a new
format symbol and an argument less (line 16). Second, if the format string
does not start with % , the format symbol is just displayed (line 19). The
function myPrintf (line 5) is the boundary condition for the recursive calls.

Let’s study fold expressions in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


https://www.educative.io/courses/generic-templates-in-cpp/qAK1PwqXKGp 2/3
3/20/22, 5:58 PM - Solution - Generic Programming Templates in C++

you instead of you applying to them. See how

(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercises Fold Expressions

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qAK1PwqXKGp 3/3
3/20/22, 5:59 PM Fold Expressions - Generic Programming Templates in C++

Fold Expressions
In this lesson, we'll study fold expressions.

We'll cover the following

• Fold Expressions (C++17)

• Two variations

Fold Expressions (C++17)#


Fold expressions is a nice syntax to evaluate binary operators at compile-
time. Fold expressions reduce parameter packs on binary operators.

C++11 provides support for parameter packs:

1 bool all_14(){
2   return true;
3 }
4
5 template<typename T, typename ...Ts>
6 bool all_14(T t, Ts ... ts){
7   return t && all_14(ts...);
8 }

C++17 provides support for fold expressions:

1 template<typename ... Args>
2 bool all_17(Args ... args){
3   return ( ... && args);
4 }
https://www.educative.io/courses/generic-templates-in-cpp/3YXgz8j22OR 1/5
3/20/22, 5:59 PM Fold Expressions - Generic Programming Templates in C++

5
6 bool val == all_14(true, true, true, false)
7          == all_17(true, true, true, false
8          == ((true && true)&& true)&& false
9          == false;

Two variations#
The fold expression either has or does not have an initial value
The parameter pack will be processed from left or right

C++17 supports the following 32 operators in fold expressions:

+ - * / % ^ & | = < > << >> += -= *= /= %= ^= &= |= <<= >>= ==


!= <= >= && || , .* ->*

Operators with their default values:

Operator Symbol Defualt Value

Logical AND && true

Logical OR || false

Comma operator , void()

For binary operators that have no default value, you have to provide an
initial value. For binary operators that have a default value, you can specify
an initial value.

If the ellipsis stands left of the parameter pack, the parameter pack will be
processed from the left. The same holds for right. This is also true if you
(/learn)
provide an initial value.
https://www.educative.io/courses/generic-templates-in-cpp/3YXgz8j22OR 2/5
3/20/22, 5:59 PM Fold Expressions - Generic Programming Templates in C++

The following table shows the four variations and their Haskell pendants.
The C++17 standard requires that fold expressions with initial value use the
same binary operator op .

C++ templates support Haskells fold* variants at compile-time, i.e., foldl ,


foldl1 , foldr and foldr1

Fold Expressions Haskell Description

Processes from left


… op pack fold1 op list
with operator op

Processes from right


pack op … foldr1 op list
with operator op

Processes from left


init op … op pack foldl op init list with operator op and
initial value init

Processes from right


pack op … op init foldr op init list with operator op and
initial value init

The C++ and Haskell variations differ in two points. The C++ version uses the
default value as the initial value while the Haskell version uses the first
element as the initial value. The C++ version processes the parameter pack at
compile-time and the Haskell version, at run time.

The small code snippet shows once more the algorithm all – this time, we
use true as the initial value.
https://www.educative.io/courses/generic-templates-in-cpp/3YXgz8j22OR 3/5
3/20/22, 5:59 PM Fold Expressions - Generic Programming Templates in C++
use true as the initial value.

template<typename... Args>

bool all(Args... args){ 

    return (true && ... && args); 

To learn more about fold expressions, click here


(https://en.cppreference.com/w/cpp/language/fold).

In the next lesson, we’ll have a look at the examples of fold expressions.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solution - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/3YXgz8j22OR 4/5
3/20/22, 5:59 PM Fold Expressions - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/3YXgz8j22OR 5/5
3/20/22, 8:11 PM - Examples - Generic Programming Templates in C++

- Examples
In this lesson, we'll look at an examples of the fold expressions.

We'll cover the following

• Example 1: Fold Expression

• Explanation
• Example 2: String Concatenation

• Explanation

Example 1: Fold Expression#


1 // foldExpression.cpp
2
3 #include <iostream>
4
5 template<typename... Args>
6 bool all(Args... args) { return (... && args); }
7
8 template<typename... Args>
9 bool any(Args... args) { return (... || args); }
10
11 template<typename... Args>
12 bool none(Args... args) { return not(... || args); }
13
14 (/learn)
15 int main(){
16     
17   std::cout << std::endl;
18
19   std::cout << std::boolalpha;
20
21   std::cout << "all(true): " << all(true) << std::endl;
22   std::cout << "any(true): " << any(true) << std::endl;
23 std::cout << "none(true): " << none(true) << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 1/4
3/20/22, 8:11 PM - Examples - Generic Programming Templates in C++
23   std::cout << "none(true): " << none(true) << std::endl;
24   
25   std::cout << std::endl;
26
27   std::cout << "all(true, true, true, false): " << all(true, true, true, false) << s
28   std::cout << "any(true, true, true, false): " << any(true, true, true, false) << s
29   std::cout << "none(true, true, true, false): " << none(true, true, true, false) <<
30   
31   std::cout << std::endl;
32   
33   std::cout << "all(false, false, false, false): " << all(false, false, false, false
34   std::cout << "any(false, false, false, false): " << any(false, false, false, false
35   std::cout << "none(false, false, false, false): " << none(false, false, false, fal
36   
37   std::cout << std::endl;
38 }

Output 1.38s

all(true, true, true, false): false

any(true, true, true, false): true

none(true, true, true, false): false

all(false, false, false, false): false

any(false, false, false, false): false

none(false, false, false, false): true

Explanation#
In the above example, we have three predicates.

all function returns true only if all the values passed to it are true ,
else false because we’re using && as an operator.

any function returns true if any passed value is true , else false
because we’re using || as an operator.

https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 2/4
3/20/22, 8:11 PM - Examples - Generic Programming Templates in C++

none function returns true only if all the passed parameters are false
because we’re using || operator with not and it will invert the result.

Example 2: String Concatenation#


1 #include <iostream>
2 #include <string>
3
4 template<typename ...Args>
5 auto addLeft(Args ... args){
6     return (std::string("0") + ... + args); // (((std::string("0")+"1")+"2")+"3")
7 }
8
9 template<typename ...Args>
10 auto addRight(Args ... args){
11     return (args + ... + std::string("0")); // ("1"+("2"+("3" + std::string("0"))))
12 }
13
14 int main(){
15     
16     std::cout << addLeft("1", "2", "3") << std::endl;    // 0123
17     std::cout << addRight("1", "2", "3") << std::endl;   // 1230
18 }
19

Output 1.63s

0123

1230

Explanation#
https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 3/4
Explanation#
3/20/22, 8:11 PM - Examples - Generic Programming Templates in C++

The above-mentioned example shows the difference between left and right
fold. We had to start with a std::string(“0”) and not “0” because “0” +
“1” gives an error. String concatenation requires at least one string.

We’ll solve an exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Fold Expressions - Exercise

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 4/4
3/20/22, 6:02 PM - Examples - Generic Programming Templates in C++

- Examples
In this lesson, we'll look at an examples of the fold expressions.

We'll cover the following

• Example 1: Fold Expression

• Explanation
• Example 2: String Concatenation

• Explanation

Example 1: Fold Expression#


(/learn)
3 #include <iostream>
4
5 template<typename... Args>
6 bool all(Args... args) { return (... && args); }
7
8 template<typename... Args>
9 bool any(Args... args) { return (... || args); }
10
11 template<typename... Args>
12 bool none(Args... args) { return not(... || args); }
13
14
15 int main(){
16     
17   std::cout << std::endl;
18
19   std::cout << std::boolalpha;
20
21   std::cout << "all(true): " << all(true) << std::endl;
22   std::cout << "any(true): " << any(true) << std::endl;
23   std::cout << "none(true): " << none(true) << std::endl;
24   
25   std::cout << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 1/4
3/20/22, 6:02 PM - Examples - Generic Programming Templates in C++

26
27   std::cout << "all(true, true, true, false): " << all(true, true, true, false) << s
28   std::cout << "any(true, true, true, false): " << any(true, true, true, false) << s
29   std::cout << "none(true, true, true, false): " << none(true, true, true, false) <<
30   
31   std::cout << std::endl;
32   
33   std::cout << "all(false, false, false, false): " << all(false, false, false, false
34 std::cout << "any(false false false false): " << any(false false false false

Output 1.37s

all(true): true

any(true): true

none(true): false

all(true, true, true, false): false

any(true, true, true, false): true

none(true, true, true, false): false

Explanation#
In the above example, we have three predicates.

all function returns true only if all the values passed to it are true ,
else false because we’re using && as an operator.

any function returns true if any passed value is true , else false
because we’re using || as an operator.

none function returns true only if all the passed parameters are false
because we’re using || operator with not and it will invert the result.

Example 2: String Concatenation#


https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 2/4
3/20/22, 6:02 PM - Examples - Generic Programming Templates in C++

1 #include <iostream>
2 #include <string>
3
4 template<typename ...Args>
5 auto addLeft(Args ... args){
6     return (std::string("0") + ... + args); // (((std::string("0")+"1")+"2")+"3")
7 }
8
9 template<typename ...Args>
10 auto addRight(Args ... args){
11     return (args + ... + std::string("0")); // ("1"+("2"+("3" + std::string("0"))))
12 }
13
14 int main(){
15     
16     std::cout << addLeft("1", "2", "3") << std::endl;    // 0123
17     std::cout << addRight("1", "2", "3") << std::endl;   // 1230
18 }
19

Output 2.34s

0123

1230

Explanation#
The above-mentioned example shows the difference between left and right
fold. We had to start with a std::string(“0”) and not “0” because “0” +
“1” gives an error. String concatenation requires at least one string.

We’ll solve an exercise in the next lesson


https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 3/4
3/20/22, 6:02 PM - Examples - Generic Programming Templates in C++
We ll solve an exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Fold Expressions - Exercise

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 4/4
3/20/22, 6:03 PM - Examples - Generic Programming Templates in C++

- Examples
In this lesson, we'll look at an examples of the fold expressions.

We'll cover the following

• Example 1: Fold Expression

• Explanation
• Example 2: String Concatenation

• Explanation

Example 1: Fold Expression#


1 // foldExpression.cpp
2
3 #include <iostream>
4
5 template<typename... Args>
6 bool all(Args... args) { return (... && args); }
7
8 template<typename... Args>
9 bool any(Args... args) { return (... || args); }
10
11 template<typename... Args>
12 bool none(Args... args) { return not(... || args); }
13
14
15 int main(){
16     
17   std::cout << std::endl;
18
19   std::cout << std::boolalpha;
20
21   std::cout << "all(true): " << all(true) << std::endl;
22   std::cout << "any(true): " << any(true) << std::endl;
23 std::cout << "none(true): " << none(true) << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 1/5
3/20/22, 6:03 PM - Examples - Generic Programming Templates in C++
23   std::cout << "none(true): " << none(true) << std::endl;
24   
25   std::cout << std::endl;
26
27   std::cout << "all(true, true, true, false): " << all(true, true, true, false) << s
28   std::cout << "any(true, true, true, false): " << any(true, true, true, false) << s
29   std::cout << "none(true, true, true, false): " << none(true, true, true, false) <<
30   
31   std::cout << std::endl;
32   
33   std::cout << "all(false, false, false, false): " << all(false, false, false, false
34   std::cout << "any(false, false, false, false): " << any(false, false, false, false
35   std::cout << "none(false, false, false, false): " << none(false, false, false, fal
36   
37   std::cout << std::endl;
38 }

Output 1.37s

all(true): true

any(true): true

none(true): false

all(true, true, true, false): false

any(true, true, true, false): true

none(true, true, true, false): false

https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 2/5
3/20/22, 6:03 PM - Examples - Generic Programming Templates in C++

Explanation#
In the (/learn)
above example, we have three predicates.

all function returns true only if all the values passed to it are true ,
else false because we’re using && as an operator.

any function returns true if any passed value is true , else false
because we’re using || as an operator.

none function returns true only if all the passed parameters are false
because we’re using || operator with not and it will invert the result.

Example 2: String Concatenation#


1 #include <iostream>
2 #include <string>
3
4 template<typename ...Args>
5 auto addLeft(Args ... args){
6     return (std::string("0") + ... + args); // (((std::string("0")+"1")+"2")+"3")
7 }
8
9 template<typename ...Args>
10 auto addRight(Args ... args){
11     return (args + ... + std::string("0")); // ("1"+("2"+("3" + std::string("0"))))
12 }
13
14 int main(){
15     
16     std::cout << addLeft("1", "2", "3") << std::endl;    // 0123
17     std::cout << addRight("1", "2", "3") << std::endl;   // 1230
18 }
19

https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 3/5
3/20/22, 6:03 PM - Examples - Generic Programming Templates in C++

Output 2.34s

0123

1230

Explanation#
The above-mentioned example shows the difference between left and right
fold. We had to start with a std::string(“0”) and not “0” because “0” +
“1” gives an error. String concatenation requires at least one string.

We’ll solve an exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Fold Expressions - Exercise

Mark as Completed

Report an Issue
https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 4/5
3/20/22, 6:03 PM - Examples - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/R8zjBEkQMWE 5/5
3/20/22, 6:04 PM - Exercise - Generic Programming Templates in C++

(/learn)

- Exercise
In this lesson, we'll solve an exercise.

We'll cover the following

• Problem Statement

Problem Statement#
Write two sum functions which use the fold expressions to add all the values
passed as arguments:

One function without an initial value.


One function with an initial value.

1 #include <iostream>
2
3 // implement a function sum without an intital value here
4
5 // implement a function sum with an intital value here
6
7 int main(){
8   // call your functions here
9 }

In the next lesson, we’ll look at the solution for this exercise.

https://www.educative.io/courses/generic-templates-in-cpp/N0o2olBQ2vD 1/2
3/20/22, 6:04 PM - Exercise - Generic Programming Templates in C++

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Examples - Solution

Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/N0o2olBQ2vD 2/2
3/20/22, 6:05 PM - Solution - Generic Programming Templates in C++

- Solution
Let's have a look at the solution review for the last exercise.

We'll cover the following

• Solution Review

• Explanation

Solution Review#
1 // sum.cpp
2
3 #include <iostream>
4
5 template<typename ...Args>     // Without an initial value
6 auto sum(Args&& ... args){
7     return ( ... + args);
8 }
9
10 template<typename T, typename ...Args>          // with an initial value    
11 auto sumWithStart(T&& t, Args&& ... args){
12     return ( t + ... + args);
13 }
14
15 int main(){
16   std::cout << sum(1, 2, 3) << std::endl;
17   std::cout << sumWithStart(20, 1, 2, 3) << std::endl;
18 }

https://www.educative.io/courses/generic-templates-in-cpp/RMKoMBMq4gL 1/3
3/20/22, 6:05 PM - Solution - Generic Programming Templates in C++

Output 1.7s

26
(/learn)

Explanation#
In the above code, we have declared two functions, i.e., sum and
sumWithStart.

sum function takes a list of arguments without any initial value and
returns their sum.

sumWithStart function takes a list of arguments and uses the first


element of the list as the initial value and adds all the successive
elements to this initial value.

Let’s move on to friends in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

https://www.educative.io/courses/generic-templates-in-cpp/RMKoMBMq4gL 2/3
3/20/22, 6:05 PM - Solution - Generic Programming Templates in C++

- Exercise Friends

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/RMKoMBMq4gL 3/3
3/20/22, 6:05 PM Friends - Generic Programming Templates in C++

Friends
Let's discuss friends in this lesson.

We'll cover the following

• Friends

• General Friends
• Special Friends

• Friend to Types

Friends#
Friends of a class template have access to all members of the class template.

A class or a class template can have a friendship to class or class templates,


function or function templates, and types.

Rules:

1. The declaration of friends can be made at an arbitrary place in the class


declaration.
2. The access rights in the class have no influence.

3. Friendship will not be inherited.


4. Friendship is not transitive.

A friend has unrestricted access to the members of the class.

https://www.educative.io/courses/generic-templates-in-cpp/JQ3NDVv9xxg 1/4
3/20/22, 6:05 PM Friends - Generic Programming Templates in C++

General Friends#
A class or a class template can grant friendship to each instance of a class
template or a function template.

1 template <typename T> int myFriendFunction(T); 
2
3 template <typename T> class MyFriend;
4
5 (/learn)
template <typename T> 
6 class GrantingFriendshipAsClassTemplate{
7   template <typename U> friend int myFriendFunction(U); 
8   template <typename U> friend class MyFriend; 
9   ...

When a class template grants friendship to a template, the typename of


the class template should be different from the typename of the
template. If both use the same name, the friendship is only granted for
the same types.

Special Friends#
A special friendship is a friendship that depends on the type of the template
parameter.

1 template <typename T> int myFriendFunction(T);
2 template <typename T> class MyFriend;
3
4 template <typename T>
5 class GrantingFriendshipAsClassTemplate{
6   friend int myFriendFunction<>(double);
7   friend class MyFriend<int>
8   friend class MyFriend<T>;
https://www.educative.io/courses/generic-templates-in-cpp/JQ3NDVv9xxg 2/4
3/20/22, 6:05 PM Friends - Generic Programming Templates in C++

If the name of the template parameter is identical to the name of the


template parameter granting the friendship, the friendship will be between
instances of the same type.

Friend to Types#
A class template can grant its friendship to a type parameter.

template <typename T>

class Array{

  friend T; 

  ...

};

Array<Account> myAccount;

To know more about friends, click here


(https://en.cppreference.com/w/cpp/language/friend).

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solution - Examples

Mark as Completed

https://www.educative.io/courses/generic-templates-in-cpp/JQ3NDVv9xxg 3/4
3/20/22, 6:05 PM Friends - Generic Programming Templates in C++

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/JQ3NDVv9xxg 4/4
3/20/22, 6:07 PM - Examples - Generic Programming Templates in C++

- Examples
In this lesson, we'll look at a few examples of using templates with friends.

We'll cover the following

• Example 1: Class Template General Friendship

• Explanation
• Example 2: Class Template Special Friendship

• Explanation
• Example 3: Class Template Type Friendship

• Explanation

Example 1: Class Template General


Friendship#
1 // templateClassTemplateGeneralFriendship.cpp
2
3 #include <iostream>
4
5 template <typename T> void myFriendFunction(T);
6 template <typename U> class MyFriend;
7
8
9 class GrantingFriendshipAsClass{
10
11   template <typename U> friend void myFriendFunction(U);
12   template <typename U> friend class MyFriend;
13
14 private:
15   std::string secret{"My secret from GrantingFriendshipAsClass."};
16
https://www.educative.io/courses/generic-templates-in-cpp/7nj8Kn01Nr8 1/7
3/20/22, 6:07 PM - Examples - Generic Programming Templates in C++
16
17 };
18
19 template <typename T>
20 class GrantingFriendshipAsClassTemplate{
21
22   template <typename U> friend void myFriendFunction(U);
23   template <typename U> friend class MyFriend;
24
25 private:
26   std::string secret{"My secret from GrantingFriendshipAsClassTemplate."};
27
28 };
29
30 template <typename T>
31 void myFriendFunction(T){
32   GrantingFriendshipAsClass myFriend;
33   std::cout << myFriend.secret << std::endl;
34
35   GrantingFriendshipAsClassTemplate<double> myFriend1;
36   std::cout << myFriend1.secret << std::endl;
37 }
38
39 template <typename T>
40 class MyFriend{
41 public:
42   MyFriend(){
43     GrantingFriendshipAsClass myFriend;
44     std::cout << myFriend.secret << std::endl;
45
46     GrantingFriendshipAsClassTemplate<T> myFriend1;
47     std::cout << myFriend1.secret << std::endl;
48   }
49 };
50
51 int main(){
52
53   std::cout << std::endl;
54
55   int a{2011};
56   myFriendFunction(a);
57
58   MyFriend<double> myFriend;
59
60   std::cout << std::endl;
61
62 }
63

https://www.educative.io/courses/generic-templates-in-cpp/7nj8Kn01Nr8 2/7
3/20/22, 6:07 PM - Examples - Generic Programming Templates in C++

Output 1.58s

My secret from GrantingFriendshipAsClass.

My secret from GrantingFriendshipAsClassTemplate.

My secret from GrantingFriendshipAsClass.

My secret from GrantingFriendshipAsClassTemplate.

Explanation#
In the above example, we have created a function myFriendFunction and a
class MyFriend. We have defined two classes: GrantingFriendshipAsClass
and GrantingFriendshipAsClassTemplate . As the name mentioned as well, we
are using one class with template and one without a template. The class
MyFriend and the function myFriendFunction have access to the private
members of the other classes by using a friend keyword. We have defined a
private variable secret which is of a string type and can be called with the
object of myFriendFunction and MyFriend.

Example 2: Class Template Special


Friendship#
1 // templateClassTemplateSpecialFriendship.cpp
2
3 #include <iostream>
4
5 template <typename T> void myFriendFunction(T);
6 template <typename U> class MyFriend;
7
8
9 class GrantingFriendshipAsClass{
https://www.educative.io/courses/generic-templates-in-cpp/7nj8Kn01Nr8 3/7
3/20/22, 6:07 PM - Examples - Generic Programming Templates in C++

10
11   friend void myFriendFunction<>(int);
12   friend class MyFriend<int>;
13
14 private:
15   std::string secret{"My secret from GrantingFriendshipAsClass."};
16
17 };
18
19 template <typename T>
20 class GrantingFriendshipAsClassTemplate{
21
22   friend void myFriendFunction<>(int);
23   friend class MyFriend<int>;
24   friend class MyFriend<T>;
25
26 private:
27   std::string secret{"My secret from GrantingFriendshipAsClassTemplate."};
28
29 };
30
31 template <typename T>
32 void myFriendFunction(T){
33   GrantingFriendshipAsClass myFriend;
34   std::cout << myFriend.secret << std::endl;
35
36   GrantingFriendshipAsClassTemplate<T> myFriend1;
37   std::cout << myFriend1.secret << std::endl;
38 }
39
40 template <typename T>
41 class MyFriend{
42 public:
43   MyFriend(){
44     GrantingFriendshipAsClass myFriend;
45     std::cout << myFriend.secret << std::endl;
46
47     GrantingFriendshipAsClassTemplate<int> myFriendInt;
48     std::cout << myFriendInt.secret << std::endl;
49
50     GrantingFriendshipAsClassTemplate<T> myFriendT;
51     std::cout << myFriendT.secret << std::endl;
52   }
53 };
54
55 int main(){
56
57   std::cout << std::endl;
58
59   int a{2011};
60   myFriendFunction(a);
61
https://www.educative.io/courses/generic-templates-in-cpp/7nj8Kn01Nr8 4/7
3/20/22, 6:07 PM - Examples - Generic Programming Templates in C++
61
62   MyFriend<int> myFriend;
63
64   std::cout << std::endl;
65
66 }
67

Output 3.02s

My secret from GrantingFriendshipAsClass.

My secret from GrantingFriendshipAsClassTemplate.

My secret from GrantingFriendshipAsClass.

My secret from GrantingFriendshipAsClassTemplate.

My secret from GrantingFriendshipAsClassTemplate.

Explanation#
This example is similar to example 1 with a small change; we have explicitly
stated the type of class template to int . Now, the class template is called for
int and also for any other type mentioned in the typename portion.

Example 3: Class Template Type


Friendship#
1 // templateClassTemplateTypeFriendship.cpp
2
3 #include <iostream>
4
5 template <typename T>
6 class Bank{
7   std::string secret{"Import secret from the bank."};
https://www.educative.io/courses/generic-templates-in-cpp/7nj8Kn01Nr8 5/7
3/20/22, 6:07 PM - Examples - Generic Programming Templates in C++
8   friend T;
9 };
10
11 class Account{
12 public:
13   Account(){
14     Bank<Account> bank;
15     std::cout << bank.secret << std::endl;
16   }
17 };
18
19 int main(){
20
21   std::cout << std::endl;
22
23   Account acc;
24
25   std::cout << std::endl;
26 (/learn)
27 }
28

Output 1.28s

Import secret from the bank.

Explanation#
In the above code, we have created an Account class which contains the
Bank class object. We can access the Bank class member secret with the
help of friend . Now, the value stored in the secret is accessible in the
Account class.

https://www.educative.io/courses/generic-templates-in-cpp/7nj8Kn01Nr8 6/7
3/20/22, 6:07 PM - Examples - Generic Programming Templates in C++

We’ll solve an exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Friends - Exercise

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/7nj8Kn01Nr8 7/7
3/20/22, 6:08 PM - Exercise - Generic Programming Templates in C++

- Exercise
Let's solve an exercise in this lesson.

We'll cover the following

• Problem Statement

Problem Statement#
Make the public member elem a private member of Array . How does that
affect the implementation of the assignment operator?

1 #include <algorithm>
2 #include <iostream>
3 #include <vector>
4
5 template <typename T, int N>
6 class Array{
7
8 public:
9   Array()= default;
10
11   template <typename T2>
12   Array<T, N>& operator=(const Array<T2, N>& arr){
13     static_assert(std::is_convertible<T2, T>::value, "Cannot convert source type to 
14     elem.clear();
15     elem.insert(elem.begin(), arr.elem.begin(), arr.elem.end());
16     return *this;
17   }
18
19   int getSize() const;
20   // you need to make the `elem` private and then run it
21   std::vector<T> elem;
22 };
23
24 template <typename T int N>
https://www.educative.io/courses/generic-templates-in-cpp/RL2W0DrZkLK 1/3
3/20/22, 6:08 PM - Exercise - Generic Programming Templates in C++
24 template <typename T, int N>
25 int Array<T, N>::getSize() const {
26   return N;
(/learn)
27 }
28
29
30 int main(){
31
32   // uncomment these line after the above implementation
33   
34   /*
35   Array<double, 10> doubleArray{};
36   Array<int, 10> intArray{};
37
38   doubleArray = intArray;
39
40   */
41 }

Succeeded

Let’s move on to the solution review of this exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

https://www.educative.io/courses/generic-templates-in-cpp/RL2W0DrZkLK 2/3
3/20/22, 6:08 PM - Exercise - Generic Programming Templates in C++
- Examples - Solution

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/RL2W0DrZkLK 3/3
3/20/22, 6:09 PM - Solution - Generic Programming Templates in C++

- Solution
Let's have a look at the solution review of the last exercise in this lesson.

We'll cover the following

• Solution Review

• Explanation

Solution Review#
1 //templateClassTemplateMethods2.cpp
2
3 #include <algorithm>
4 #include <iostream>
5 #include <vector>
6
7 template <typename T, int N>
8 (/learn)
class Array{
9
10 public:
11   Array()= default;
12   
13   template <typename T2, int M> friend class Array;  
14
15   template <typename T2>
16   Array<T, N>& operator=(const Array<T2, N>& arr){
17     static_assert(std::is_convertible<T2, T>::value, "Cannot convert source type to 
18     elem.clear();
19     elem.insert(elem.begin(), arr.elem.begin(), arr.elem.end());
20     return *this;
21   }
22
23   int getSize() const;
24
25 private:
26   
https://www.educative.io/courses/generic-templates-in-cpp/gknPmvqxGYY 1/3
3/20/22, 6:09 PM - Solution - Generic Programming Templates in C++

27   std::vector<T> elem;
28 };
29
30 template <typename T, int N>
31 int Array<T, N>::getSize() const {
32   return N;
33 }
34
35 int main(){
36
37   Array<double, 10> doubleArray{};
38   Array<int, 10> intArray{};
39
40   doubleArray = intArray;
41
42 }

Succeeded

Explanation#
In the above code, we have created an Array class in which we have defined
a method = which copies the entries of integer array to double array.
getSize function returns the size of the array passed in the argument.
Template classes with different template arguments are considered of
different types, which is why Array<int, 10> and Array<double, 10> aren’t
able to access each other. And that’s why the Array template class has to be
declared a friend of itself.

To access the private elem of arr in line 19, class Array is a friend of the
class Array in line 13.

In the next lesson, we’ll study dependent names.


https://www.educative.io/courses/generic-templates-in-cpp/gknPmvqxGYY 2/3
3/20/22, 6:09 PM - Solution - Generic Programming Templates in C++
In the next lesson, we ll study dependent names.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise Dependent Names

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/gknPmvqxGYY 3/3
3/20/22, 6:10 PM Dependent Names - Generic Programming Templates in C++

Dependent Names
In this lesson, we'll study dependent names.

We'll cover the following

• Dependent Names

• Two-phase name lookup


• The Dependent Name is a Type typename

• The Dependent Name is a Template .template

Dependent Names#
A dependent name is essentially a name that depends on a template
parameter. A dependent name can be a type, a non-type, or a template-
template parameter.

If you use a dependent name in a template declaration or template


definition, the compiler has no idea, whether this name refers to a type, a
non-type, or a template parameter. In this case, the compiler assumes that
the dependent name refers to a non-type, which may be wrong.

Let’s have a look at the example of dependent names:

1 template<typename T>
2 struct X : B<T>   // "B<T>" is dependent on T
3 {
4     typename T::A* pa;   // "T::A" is dependent on T
5     void f(B<T>* pb) {
6         static int i = B<T>::i;    // "B<T>::i" is dependent on T
https://www.educative.io/courses/generic-templates-in-cpp/g7nlq1oqEq9 1/4
3/20/22, 6:10 PM Dependent Names - Generic Programming Templates in C++
7         pb->j++;    // "pb->j" is dependent on T
8     }
9 };

T is the template parameter. The names B<T> , T::A , B<T> , B<T>::i , and pb-
>j are dependent.

Two-phase name lookup#


Dependent names are resolved during template instantiation.
Non-dependent names are resolved during template definition.

A from a template parameter T is dependent, qualified name


T::A can be a

Type

Non-type
Template

The compiler assumes by default that T::A is a non-type.

The compiler has to be convinced that T::A is a type or a template.

The Dependent Name is a Type typename #


1 template <typename T> void test(){
2   std::vector<T>::const_iterator* p1;          // ERROR
3   typename std::vector<T>::const_iterator* p2; //OK
4 }

Without typename like in line 3, the expression in line 2 would be interpreted


as multiplication.

https://www.educative.io/courses/generic-templates-in-cpp/g7nlq1oqEq9 2/4
3/20/22, 6:10 PM Dependent Names - Generic Programming Templates in C++

(/learn)

The Dependent Name is a Template


.template #
1 template<typename T>
2 struct S{
3   template <typename U> void func(){}
4 }
5
6 template<typename T>
7 void func2(){
8   S<T> s;
9   s.func<T>();             // ERROR
10   s.template func<T>();    // OK
11 }

Compare lines 9 and 10. When the compiler reads the name s.func (line 9),
it decides to interpret it as non-type. This means, the < sign stands in this
case for the comparison operator but not opening square bracket of the
template argument of the generic method func . To help the parser, you have
to specify that s.func is a template like in line 10: s.template func .

To learn more about dependent names, click here


(https://en.cppreference.com/w/cpp/language/parameter_pack).

In the next lesson, we’ll look at an example of dependent names.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022
https://www.educative.io/courses/generic-templates-in-cpp/g7nlq1oqEq9 3/4
3/20/22, 6:10 PM Dependent Names - Generic Programming Templates in C++

Back Next

- Solution - Example

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/g7nlq1oqEq9 4/4
3/20/22, 6:11 PM - Example - Generic Programming Templates in C++

- Example
Let's have a look at an example of dependent names in this lesson.

We'll cover the following

• Example: Template Lookup

• Explanation

Example: Template Lookup#


1 // templateLookup.cpp
2
3 #include <iostream>
4
5 void g(double) { std::cout << "g(double)\n"; }
6
7 template<class T>
8 struct S {
9     void f() const {
10         g(1);              // non-dependent
11     }
12 };
13  
14 void g(int) { std::cout << "g(int)\n"; }
15  
16 int main(){
17     g(1);                 // calls g(int)
18  
19     S<int> s;
20     s.f();                // calls g(double)
21 }
(/learn)
22

https://www.educative.io/courses/generic-templates-in-cpp/myoYOYGNBnR 1/3
3/20/22, 6:11 PM - Example - Generic Programming Templates in C++

Output 1.69s

g(int)

g(double)

Explanation#
If we access the defined functions g with double or int type object, they
work fine. We have created the struct object S of int type in line 19.
When we try to access the g function then it follows the same order and
calls, the g with a double type parameter is defined first. The call to g() on
line 17 calls the g(int) version and the call to g() through the call to f()
on line 20 calls g(double) .

In this chapter, we have learned about the details of templates. In the next
chapter, we’ll familiarize ourselves with the techniques used in templates.
Let’s start with Automatic Return type in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

https://www.educative.io/courses/generic-templates-in-cpp/myoYOYGNBnR 2/3
3/20/22, 6:11 PM - Example - Generic Programming Templates in C++

Back Next

Dependent Names Automatic Return Type

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/myoYOYGNBnR 3/3
3/20/22, 6:11 PM Automatic Return Type - Generic Programming Templates in C++

Automatic Return Type


In this lesson, we'll look at the technique that deduces return type automatically.

We'll cover the following

• Automatic Return Type

• Automatic Return Type: C++14

Automatic Return Type#


A function template is automatically able to deduce their return type.

template <typename T1, typename T2>

auto add(T1 fir, T2 sec) -> decltype( fir + sec ) { 

  return fir + sec;

The automatic return type deduction is typically used for function


templates but can also be applied to non-template functions.

Rules:

auto : introduces the syntax for the delayed return type

auto : auto type deduction is based on the function template argument


deduction. Function template argument deduction (decays
(https://en.cppreference.com/w/cpp/types/decay)). So it means auto
https://www.educative.io/courses/generic-templates-in-cpp/g7DnLgVkjBk 1/4
3/20/22, 6:11 PM Automatic Return Type - Generic Programming Templates in C++

does not return the exact type but a decayed type such as for template

argument deduction
(https://www.educative.io/collection/page/10370001/5799373671759872/
6076820204027904)

decltype : declares the return type

The alternative function syntax is obligatory

The C++11 syntax for automatically deducing the return type breaks
the crucial principle of software development: DRY. DRY stands for
Don’t Repeat Yourself
(https://en.wikipedia.org/wiki/Don%27t_repeat_yourself).

(/learn)

Automatic Return Type: C++14#


A function template is automatically able to deduce their return type.

template <typename T1, typename T2>

auto add(T1 fir, T2 sec){

    return fir + sec;

Rules

auto: introduces the syntax for the delayed return type

decltype : declares the return type

The alternative function syntax is obligatory.

With the expression decltype(auto) , auto uses the same rules to determine
the type as decltype . This means, in particular, no decay
(https://en.cppreference.com/w/cpp/types/decay) takes place.
https://www.educative.io/courses/generic-templates-in-cpp/g7DnLgVkjBk 2/4
3/20/22, 6:11 PM Automatic Return Type - Generic Programming Templates in C++

Both declarations are identical.

   decltype(expr) v= expr;

   decltype(auto) v= expr;

The syntax also applies for the automatic return type of a function
template.

   template <typename T1, typename T2> 

   decltype(auto) add(T1 fir, T2 sec){

       return fir + sec;

   }

When a function template has more than one return statements, all
return statements must have the same type.

In the next lesson, we’ll study an example of automatic return type


deduction.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Example - Example

Mark as Completed
https://www.educative.io/courses/generic-templates-in-cpp/g7DnLgVkjBk 3/4
3/20/22, 6:11 PM Automatic Return Type - Generic Programming Templates in C++

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/g7DnLgVkjBk 4/4
3/20/22, 6:12 PM - Example - Generic Programming Templates in C++

- Example
In this lesson, we'll look at an example of the automatic return type.

We'll cover the following

• Example: Automatic Template Return Type

• Explanation

Example: Automatic Template Return


Type#
1 // templateAutomaticReturnType.cpp
2
3 #include <iostream>
4 #include <typeinfo>
5
6 template<typename T1, typename T2>
7 auto add(T1 first, T2 second) -> decltype(first + second){
8   return first + second;
9 }
10
11 int main(){
12
13   std::cout << std::endl;
14
15   std::cout << "add(1, 1)= " << add(1,1) << std::endl;
16   std::cout << "typeid(add(1, 1)).name()= " << typeid(add(1, 1)).name() << std::endl
17
18   std::cout << std::endl;
19
20   std::cout << "add(1, 2.1)= " << add(1,2.1) << std::endl;
21   std::cout << "typeid(add(1, 2.1)).name()= " << typeid(add(1, 2.1)).name() << std::
22
23   std::cout << std::endl;
24
https://www.educative.io/courses/generic-templates-in-cpp/NEwww5qlQ0m 1/3
3/20/22, 6:12 PM - Example - Generic Programming Templates in C++
24
25 (/learn)
  std::cout << "add(1000LL, 5)= " << add(1000LL,5) << std::endl;
26   std::cout << "typeid(add(1000LL, 5)).name()= " << typeid(add(1000LL, 5)).name() <<
27
28   std::cout << std::endl;
29 }

Output 1.25s

add(1, 1)= 2

typeid(add(1, 1)).name()= i

add(1, 2.1)= 3.1

typeid(add(1, 2.1)).name()= d

add(1000LL, 5)= 1005

typeid(add(1000LL, 5)).name()= x

Explanation#
The example has a function add which takes two arguments and returns
their sum. The return type of the function is deduced by the compiler by
applying the decltype operator on the sum of the arguments. The
expression typeid(add(1, 2.1)).name() such as in line 21 returns a string
representation of the type of result.

We’ll solve an exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them See how
https://www.educative.io/courses/generic-templates-in-cpp/NEwww5qlQ0m 2/3
3/20/22, 6:12 PM - Example - Generic Programming Templates in C++
you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Automatic Return Type - Exercise

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/NEwww5qlQ0m 3/3
3/20/22, 6:12 PM - Exercise - Generic Programming Templates in C++

- Exercise
In this lesson, we'll solve an exercise related to the automatic return type.

We'll cover the following

• Problem Statement

Problem Statement#
The two algorithms gcdConditional and gcdCommon , in the given code, use the
type-traits library.

Study both algorithms.


Both algorithms determine their return type at compile-time.

Why is it not possible to use auto or decltype(auto) to automatically deduce


the return type?

1 #include <iostream>
2 #include <string>
3 #include <type_traits>
4 #include <typeinfo>
5
6 template<typename T1, typename T2, 
7          typename R = typename std::conditional <(sizeof(T1) < sizeof(T2)), T1, T2>:
8 R gcdConditional(T1 a, T2 b){
9   static_assert(std::is_integral<T1>::value, "T1 should be an integral type!");
10   static_assert(std::is_integral<T2>::value, "T2 should be an integral type!");
11   if( b == 0 ){ return a; }
12   else{
13     return gcdConditional(b, a % b);
14   }
15 }
https://www.educative.io/courses/generic-templates-in-cpp/B8zMvKN4KJX 1/3
3/20/22, 6:12 PM - Exercise - Generic Programming Templates in C++
}
16
17
18 template<typename T1, typename T2, 
19          typename R = typename std::common_type<T1, T2>::type>
20 R gcdCommon(T1 a, T2 b){
21   static_assert(std::is_integral<T1>::value, "T1 should be an integral type!");
22   static_assert(std::is_integral<T2>::value, "T2 should be an integral type!");
23   if( b == 0 ){ return a; }
24   else{
25     return gcdCommon(b, a % b);
26   }
27 }
28
29 int main(){
30
31
32 (/learn)
  std::cout << std::endl;
33
34   std::cout << "gcdConditional(100, 10LL) = " << gcdConditional(100, 10LL) << std::e
35   std::cout << "gcdCommon(100, 10LL) = " << gcdCommon(100, 10LL) << std::endl;
36   
37   std::conditional <(sizeof(int) < sizeof(long long)), int, long long>::type gcd1 = 
38   auto gcd2 = gcdCommon(100, 10LL);
39   
40   std::cout << std::endl;
41   
42   std::cout << "typeid(gcd1).name() = " << typeid(gcd1).name() << std::endl;
43   std::cout << "typeid(gcd2).name() = " << typeid(gcd2).name() << std::endl;
44
45   std::cout << std::endl;
46
47 }
48

We’ll look at the solution review of this exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022
https://www.educative.io/courses/generic-templates-in-cpp/B8zMvKN4KJX 2/3
3/20/22, 6:12 PM - Exercise - Generic Programming Templates in C++

Back Next

- Example - Solution

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/B8zMvKN4KJX 3/3
3/20/22, 6:13 PM - Solution - Generic Programming Templates in C++

- Solution
In this lesson, we'll look at the solution review of the last exercise.

We'll cover the following

• Solution Review

• Explanation

Solution Review#
1 // gcdVariation.cpp
2
3 #include <iostream>
4 #include <type_traits>
5 #include <typeinfo>
6
7 template<typename T1, typename T2, 
8          typename R = typename std::conditional <(sizeof(T1) < sizeof(T2)), T1, T2>:
9 R gcdConditional(T1 a, T2 b){
10   static_assert(std::is_integral<T1>::value, "T1 should be an integral type!");
11   static_assert(std::is_integral<T2>::value, "T2 should be an integral type!");
12   if( b == 0 ){ return a; }
13   else{
14     return gcdConditional(b, a % b);
15   }
16 }
17
18
19 template<typename T1, typename T2, 
20          typename R = typename std::common_type<T1, T2>::type>
21 R gcdCommon(T1 a, T2 b){
22   static_assert(std::is_integral<T1>::value, "T1 should be an integral type!");
23   static_assert(std::is_integral<T2>::value, "T2 should be an integral type!");
24   if( b == 0 ){ return a; }
25   else{
26     return gcdCommon(b, a % b);
https://www.educative.io/courses/generic-templates-in-cpp/7nDBNLNglzB 1/3
3/20/22, 6:13 PM - Solution - Generic Programming Templates in C++

27   }
28 }
29
30 int main(){
31
32
33   std::cout << std::endl;
34
35   std::cout << "gcdConditional(100, 10LL) = " << gcdConditional(100, 10LL) << std::e
36   std::cout << "gcdCommon(100, 10LL) = " << gcdCommon(100, 10LL) << std::endl;
37   
38   std::conditional <(sizeof(int) < sizeof(long long)), int, long long>::type gcd1 = 
39   auto gcd2 = gcdCommon(100, 10LL);
40   
41   std::cout << std::endl;
42   
43   std::cout << "typeid(gcd1).name() = " << typeid(gcd1).name() << std::endl;
44   std::cout << "typeid(gcd2).name() = " << typeid(gcd2).name() << std::endl;
45
46   std::cout << std::endl;
47
48 }
49

(/learn)

Output 1.4s

gcdConditional(100, 10LL) = 10

gcdCommon(100, 10LL) = 10

typeid(gcd1).name() = i

typeid(gcd2).name() = x

Explanation#
In the above code, we have defined an automatic return type R which
returns data based on the data type passed in the function gcdCommon and
gcdConditional .

https://www.educative.io/courses/generic-templates-in-cpp/7nDBNLNglzB 2/3
3/20/22, 6:13 PM - Solution - Generic Programming Templates in C++

Automatic return type deduction can’t be used in both algorithms, because


both algorithms solve their job by recursion (lines 24 and 26). The critical
observation is that this recursion swaps their arguments. For example,
gcdCommon(a, b) invokes gcdCommon(b, a % b) . This recursion, therefore,
creates a function with different return types. Having a function with
different return types is not valid.

Let’s move on to template metaprogramming in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise Template Metaprogramming

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/7nDBNLNglzB 3/3
3/20/22, 6:14 PM Template Metaprogramming - Generic Programming Templates in C++

Template Metaprogramming
In this lesson, we'll learn about template metaprogramming.

We'll cover the following

• Template Metaprogramming

• How this all started:


• Calculating at Compile-Time

• Type Manipulations
• Explanation

• Metadata and Metafunctions

• Functions vs Meta Functions


• Pure Functional Sublanguage

Template Metaprogramming#
(/learn)

How this all started:#


1994 Erwin Unruh discovered template metaprogramming by accident.
His program failed to compile but calculated the first 30 prime numbers
at compile-time.
To prove his point, he used the error messages to display the first 30
prime numbers.

Let’s have a look at the screenshot of the error:

https://www.educative.io/courses/generic-templates-in-cpp/7n0N88x2oEA 1/8
3/20/22, 6:14 PM Template Metaprogramming - Generic Programming Templates in C++

We have highlighted the important parts in red. We hope you can see the
pattern. The program calculates at compile-time the first 30 prime numbers.
This means template instantiation can be used to do math at compile-time. It
gets even better. Template metaprogramming is Turing-complete
(https://simple.wikipedia.org/wiki/Turing_complete) and can, therefore, be
used to solve any computational problem. Of course, Turing-completeness
holds only in theory for template metaprogramming because the recursion
depth (at least 1024 with C++11) and the length of the names which are
generated during template instantiation provide some limitations.

Calculating at Compile-Time#
The Factorial program is the Hello World of template metaprogramming.

1 template <int N>
2 struct Factorial{
3     static int const value= N * Factorial<N-1>::value;
4 };
5
6 template <> struct Factorial<1>{
7     static int const value = 1;
8 };
9
https://www.educative.io/courses/generic-templates-in-cpp/7n0N88x2oEA 2/8
3/20/22, 6:14 PM Template Metaprogramming - Generic Programming Templates in C++
10 std::cout << Factorial<5>::value << std::endl;
11 std::cout << 120 << std::endl;

The call Factorial<5>::value in line 10 causes the instantiation of the


primary or general template in line 3. During this instantiation,
Factorial<4>::value will be instantiated. This recursion will end if the fully
specialized class template Factorial<1> (line 6) kicks in as the boundary
condition. Maybe, you like it more pictorial.

The following picture shows this process.

Assembler Instructions

From the assemblers point of view, the Factorial<5>::value boils down to


the constant 0x78 , which is 120.

mov 0x78, %esi

mov 0x601060, %edi

...

mov 0x78, %esi

mov 0x601060, %edi

...

Type Manipulations#
Manipulating types at compile-time is typically for template
metaprogramming
https://www.educative.io/courses/generic-templates-in-cpp/7n0N88x2oEA 3/8
3/20/22, 6:14 PM Template Metaprogramming - Generic Programming Templates in C++
metaprogramming.

1 template <typename T>
2 struct RemoveConst{
3   typedef T type; 
4 };
5
6 template <typename T> 
7 struct RemoveConst<const T>{
8   typedef T type; 
9 };
10
11 int main(){
12   std::is_same<int, RemoveConst<int>::type>::value;       // true
13   std::is_same<int, RemoveConst<const int>::type>::value; // true
14 }

Explanation#
In the code, we have defined the class template removeConst in two versions.
We have implemented removeConst the way std::remove_const is probably
implemented in the type-traits
(https://www.educative.io/collection/page/10370001/5799373671759872/6380
229176066048) library.

std::is_same from the type-traits library helps us to decide at compile-time


if both types are the same. In case of removeConst<int> , the first or general
class template kicks in; in case of removeConst<const int> , the partial
specialization for const T applies. The key observation is that both class
templates return the underlying type in lines 3 and 8, therefore, the
constness is removed.

This kind of technique, which is heavily used in the type-traits library, is a


compile-time if on types.

To jump into more details of type traits click here


(https://www.educative.io/collection/page/10370001/5799373671759872/6380
https://www.educative.io/courses/generic-templates-in-cpp/7n0N88x2oEA 4/8
3/20/22, 6:14 PM Template Metaprogramming - Generic Programming Templates in C++

229176066048).

Metadata and Metafunctions#


At compile-time, we speak about metadata and metafunctions instead of
data and functions.

Metadata: Types and integral types that are used in metafunctions.

Metafunctions: Functions that are executed at compile-time. Class


templates are used to implement metafunctions.

Return their value by ::value .

        template <> 

        struct Factorial<1>{

           static int const value = 1;

        };

Return their type by ::type .

        template <typename T> 

        struct RemoveConst<const T>{

           typedef T type;

        };

Functions vs Meta Functions#


From the conceptual view, it helps a lot to compare functions and
metafunctions.

Characteristics Functions Metafunctions

Call power(2,10) Power<2,10>::value

https://www.educative.io/courses/generic-templates-in-cpp/7n0N88x2oEA 5/8
3/20/22, 6:14 PM Template Metaprogramming - Generic Programming Templates in C++

Characteristics Functions Metafunctions

Execution Time Runtime Compile-time

Arguments Function arguments Template arguments

Arguments and re- Types, non-types and


Arbitrary values
turn value templates

Implementation Callable Class template

Data Mutable Immutable

Modification Data can be modified New data are created

State Has state Has no state

What does the table above mean for a concrete function and a concrete
metafunction?

Function Metafunction

https://www.educative.io/courses/generic-templates-in-cpp/7n0N88x2oEA 6/8
3/20/22, 6:14 PM Template Metaprogramming - Generic Programming Templates in C++

int power(int m, int n){
template<int m, int n>

    int r = 1;
struct Power{

    for(int k=1; k<=n; ++k    static int const value = m * Power<m,
){
 n-1>::value; 

       r *= m;
};

    }

    return r;
template<int m>

}
struct Power<m, 0>{


   static int const value =1; 


};

Function arguments go into round ( ) braces and template arguments


go into sharp <> braces.

int main(){

   std::cout << power(2, 10) << std::endl;          // 1024

   std::cout << Power<2, 10>::value << std::endl;   // 1024

Pure Functional Sublanguage#


Template metaprogramming is
an embedded pure functional language in the imperative language
C++.
Turing-complete. Turing-complete means, that all can be calculated
what is calculatable.
an intellectual playground for C++ experts.
the foundation for many boost (https://www.boost.org/) libraries.

https://www.educative.io/courses/generic-templates-in-cpp/7n0N88x2oEA 7/8
3/20/22, 6:14 PM Template Metaprogramming - Generic Programming Templates in C++

The template recursion depth is limited.

C++03: 17
C++11: 1024

In the next lesson, we’ll look at a few examples of template


metaprogramming.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solution - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/7n0N88x2oEA 8/8
3/20/22, 6:15 PM - Examples - Generic Programming Templates in C++

- Examples
We'll look at a few examples of template metaprogramming in this lesson.

We'll cover the following

• Example 1: Template Prime Number

• Explanation
• Example 2: Template Type Manipulation

• Explanation
• Example 3: Template Power

• Explanation

Example 1: Template Prime Number #


2 // Prime number computation by Erwin Unruh
3
4 template <int i> struct D { D(void*); operator int(); };
5
6 template <int p, int i> struct is_prime {
7     enum { prim = (p==2) || (p%i) && is_prime<(i>2?p:0), i-1> :: prim };
8 };
9
10 template <int i> struct Prime_print {
11     Prime_print<i-1> a;
12     enum { prim = is_prime<i, i-1>::prim };
13     void f() { D<i> d = prim ? 1 : 0; a.f();}
14 };
15
16 template<> struct is_prime<0,0> { enum {prim=1}; };
17 template<> struct is_prime<0,1> { enum {prim=1}; };
18
19 template<> struct Prime_print<1> {
20     enum {prim=0};
https://www.educative.io/courses/generic-templates-in-cpp/RLRgj3MoWpR 1/6
3/20/22, 6:15 PM - Examples - Generic Programming Templates in C++
{p };
21     void f() { D<1> d = prim ? 1 : 0; };
22 };
23
24 #ifndef LAST
25 #define LAST 18
26 #endif
27
28 int main() {
29  Prime_print<LAST> a;
30  a.f();
31 }
32

Explanation #
This is the original prime number program by Erwin Unruh, which was the
starting point of template metaprogramming. Current compilers will not
produce the same output as the ancient compiler, which Erwin Unruh used
more than 20 years ago.

Example 2: Template Type


Manipulation #
1 // templateTypeManipulation.cpp
2
3 #include <iostream>
4 #include <type_traits>
5
6 template <typename T>
7 struct RemoveConst{
8     typedef T type;
9 };
10
11 template <typename T>
12 struct RemoveConst<const T>{
13     typedef T type;
14 };
15
16
17 int main(){
18
19     std::cout << std::boolalpha << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/RLRgj3MoWpR 2/6
3/20/22, 6:15 PM - Examples - Generic Programming Templates in C++
20
21     std::cout << "std::is_same<int, RemoveConst<int>::type>::value: " << std::is_sam
22     std::cout << "std::is_same<int, RemoveConst<const int>::type>::value: " << std::
23     
24     std::cout << std::endl;
25  
26 }
27

Output 2.48s

std::is_same<int, RemoveConst<int>::type>::value: true

std::is_same<int, RemoveConst<const int>::type>::value: true

Explanation #
The code uses the function std::is_same from the type-traits library.
std::is_same compares the type passed and returns at compile time if they
are the same. Thanks to the type-traits function, we can verify the
RemoveConst class template from the previous subsection
(https://www.educative.io/collection/page/10370001/5799373671759872/5899
934744182784#type-manipulations).

Example 3: Template Power #


1 // templatePower.cpp
2
3 #include <iostream>
4
5 i t (i t i t ){
https://www.educative.io/courses/generic-templates-in-cpp/RLRgj3MoWpR 3/6
3/20/22, 6:15 PM - Examples - Generic Programming Templates in C++
5 int power(int m, int n){
6     int r = 1;
7     for(int k=1; k<=n; ++k) r*= m;
8     return r;
9 }
10
11 template<int m, int n>
12 struct Power{
13     static const int value = Power<m,n-1>::value * m;
14 };
15
16 template<int m>
17 struct Power<m,0>{
18     static const int value = 1;
19 };
20
21 template<int n>
22 int power2(const int& m){
23     return power2<n-1>(m) * m;
24 }
25
26 template<>
27 int power2<1>(const int& m){
28     return m;
29 }
30
31 template<>
32 int power2<0>(const int&){
33     return 1;
34 }
35
36 int main(){
37     
38     std::cout << std::endl;
39     
40     std::cout << "power(2,10):        " << power(2,10) << std::endl;
41     std::cout << "power2<10>(2):       " << power2<10>(2) << std::endl;
42     std::cout << "Power<2,10>::value: " << Power<2,10>::value << std::endl;
43     
44     std::cout << std::endl;
45 }
46

Output 1.36s

https://www.educative.io/courses/generic-templates-in-cpp/RLRgj3MoWpR 4/6
3/20/22, 6:15 PM - Examples - Generic Programming Templates in C++

power(2,10): 1024

power2<10>(2): 1024

(/learn)
Power<2,10>::value: 1024

Explanation #
The program calculates 210 in three different variants.

power is a function in line 5

Power is a class template in line 12

power2 is a function template in line 22

The key question is: When is the function executed?

power runs at runtime

Power runs at compile-time

power2 runs at runtime and at compile-time too


the template argument is evaluated at compile-time

the function argument is evaluated at runtime

We’ll solve an exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

https://www.educative.io/courses/generic-templates-in-cpp/RLRgj3MoWpR 5/6
3/20/22, 6:15 PM - Examples - Generic Programming Templates in C++

Back Next

Template Metaprogramming - Exercise

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/RLRgj3MoWpR 6/6
3/20/22, 6:16 PM - Exercise - Generic Programming Templates in C++

- Exercise
Let's solve an exercise in this lesson.

We'll cover the following

• Problem Statement

Problem Statement#
Implement the metafunction to calculate the factorial of a number.

1 #include <iostream>
2
3 template <int N> 
(/learn)
4 struct Factorial{
5   // Implement the functionality to run the code in the main
6 };
7
8 int main(){
9   // Uncomment the given code after implementing the Factorial function
10
11    // std::cout << Factorial<5>::value << std::endl;
12 }
13

In the next lesson, we’ll look at the solution of this exercise.

https://www.educative.io/courses/generic-templates-in-cpp/39QDv3WJAQr 1/2
3/20/22, 6:16 PM - Exercise - Generic Programming Templates in C++

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Examples - Solution

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/39QDv3WJAQr 2/2
3/20/22, 6:17 PM - Solution - Generic Programming Templates in C++

- Solution
Let's have a look at a solution review for the last exercise.

We'll cover the following

• Solution Review

• Explanation

Solution Review#
1 // templateFactorial.cpp
2
3 #include <iostream>
4
5 template <int N> 
6 struct Factorial{
7     static int const value = N * Factorial<N-1>::value;
8 };
9
10 template <> 
11 struct Factorial<1>{
12     static int const value = 1;
13 };
14
15 int main(){
16     std::cout << Factorial<10>::value << std::endl;
17 }
18

https://www.educative.io/courses/generic-templates-in-cpp/YQM4OWvwRg9 1/3
3/20/22, 6:17 PM - Solution - Generic Programming Templates in C++

Output 1.39s

3628800

(/learn)

Explanation#
The Factorial function calls itself recursively by storing the result of each
iteration in value . For the base case, the result is multiplied by 1 in line 12
and the answer is stored in value.

To be precise, what looks like a recursion, like in the case of Factorial ,


is not a recursion. Each invocation of Factorial<N> triggers a new
instantiation Factorial<N-1> in line 7.

In the next lesson, we’ll discuss type traits.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise Type-Traits Overview

Mark as Completed
https://www.educative.io/courses/generic-templates-in-cpp/YQM4OWvwRg9 2/3
3/20/22, 6:17 PM - Solution - Generic Programming Templates in C++
Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/YQM4OWvwRg9 3/3
3/20/22, 6:17 PM Type-Traits Overview - Generic Programming Templates in C++

Type-Traits Overview
In this lesson, we'll study the type traits library and its goals along with type-checks. This
section could only provide an overview of the many functions of the type-traits library.

We'll cover the following

• Type-Traits Library

• Type-Traits: Goals
• Optimization

• Correctness
• Type Checks

Type-Traits Library #
Type-traits enable type checks, type comparisons, and type modifications at
compile-time.

Below are some applications of template metaprogramming:

Programming at compile-time
Programming with types and values

Compiler translates the templates and transforms it in C++ source code

We need to add a type_traits library in the header to enable all the


functions present in the library.

#include <type_traits>

https://www.educative.io/courses/generic-templates-in-cpp/m7Ny81pnZ5p 1/6
3/20/22, 6:17 PM Type-Traits Overview - Generic Programming Templates in C++

Type-Traits: Goals #
If you look carefully, you’ll see that type-traits have a significant
optimization potential. In the first step, type-traits help to analyze the code
at compile-time and in the second step, to optimize the code based on that
analysis. How is that possible? Depending on the type of variable, a faster
variant of an algorithm will be chosen.

Optimization #
Code that optimizes itself. Depending on the type of a variable another
code will be chosen.
Optimized version of std::copy , std::fill , or std::equal is used so
that algorithms can work on memory blocks.
The optimized version of operations happens on all the elements in a
container in one step and not on each element individually.

Correctness #
Type checks will be performed at compile-time.
Type information, together with static_assert , defines the
requirements for the code.
With the concepts
(https://www.educative.io/collection/page/10370001/5799373671759872/
5589499255980032) in C++20, the correctness aspect of the type-traits
becomes less important.

Type Checks #
C++ has 14 primary type categories. They are complete and orthogonal. This
th t ht i b
https://www.educative.io/courses/generic-templates-in-cpp/m7Ny81pnZ5p f tl t t Th h k 2/6
3/20/22, 6:17 PM Type-Traits Overview - Generic Programming Templates in C++

means, that each type is a member of exactly one type category. The check
for the type categories is independent of the type qualifiers const or
volatile .

Let’s have a look at these categories syntactically:

1 template <class T> struct is_void;
2 template <class T> struct is_integral;
3 template <class T> struct is_floating_point;
4 template <class T> struct is_array;
5 template <class T> struct is_pointer;
6 template <class T> struct is_reference;
7 template <class T> struct is_member_object_pointer;
8 template <class T> struct is_member_function_pointer;
9 template <class T> struct is_enum;
10 template <class T> struct is_union;
11 template <class T> struct is_class;
12 template <class T> struct is_function;
13 template <class T> struct is_lvalue_reference;
14 template <class T> struct is_rvalue_reference;

We can divide the type-traits into smaller sets for simplicity.

Primary type category ( ::value )

 std::is_pointer<T>,

 std::is_integral<T>,

 std::is_floating_point<T>

Composed type category ( ::value )

 std::is_arithmetic<T>,

 std::is_object<T>

Type comparisons ( ::value )

 std::is_same<T,U>, 

 std::is_base_of<Base,Derived>, 
std::is convertible<From To>
https://www.educative.io/courses/generic-templates-in-cpp/m7Ny81pnZ5p 3/6
3/20/22, 6:17 PM Type-Traits Overview - Generic Programming Templates in C++
 std::is_convertible<From,To>

Type transformation ( ::type )

 std::add_const<T>,

 std::remove_reference<T> 

 std::make_signed<T>,

 std::make_unsigned<T>

Others ( ::type )

 std::enable_if<bool,T> 

 std::conditional<bool,T,F> 

 std::common_type<T1, T2, T3, ... >

(/learn)
The above-mentioned functions, from the type-traits, give only a rough idea
of their power. To learn more about type checks, click here
(https://en.cppreference.com/w/cpp/header/type_traits). The above-
mentioned functions are available on the given link with more detail.

1 // removeConst.cpp
2
3 #include <iostream>
4 #include <string>
5 #include <type_traits>
6
7 namespace rgr{
8   
9   template<class T, class U>
10   struct is_same : std::false_type {};
11  
12   template<class T>
13   struct is_same<T, T> : std::true_type {};
14
15   template< class T > 
16   struct remove_const{ 
17     typedef T type; 
18   };
19
20   template< class T > 
21   struct remove_const<const T> { 
22     typedef T type; 
23 };
https://www.educative.io/courses/generic-templates-in-cpp/m7Ny81pnZ5p 4/6
3/20/22, 6:17 PM Type-Traits Overview - Generic Programming Templates in C++
23   };
24 }
25
26
27 int main(){
28   
29   std::cout << std::boolalpha << std::endl;
30   
31   std::cout << std::is_same<int,std::remove_const<const int>::type>::value << std::e
32   std::cout << rgr::is_same<int,rgr::remove_const<const int>::type>::value << std::e
33   
34   typedef rgr::remove_const<double>::type myDouble;
35   std::cout << rgr::is_same<double,myDouble>::value << std::endl;
36   
37   typedef rgr::remove_const<const std::string>::type myString;
38   std::cout << rgr::is_same<std::string,myString>::value << std::endl;
39   
40   typedef rgr::remove_const<std::add_const<int>::type>::type myInt;
41   std::cout << rgr::is_same<int,myInt>::value << std::endl;
42   
43   std::cout << std::endl;
44   
45 }
46

We have implemented is_same and remove_const in the namespace rgr .


This corresponds to the type-traits library. For simplicity reason, we use the
static constants std::false_type and std::true_type (lines 10 and 13).
Thanks to the base class std::false_type , the class template has a member
value. Respectively for std::true_type . The key observation of the class
template is_same is to distinguish the general template (lines 9 and 10) from
the partially specialized template (line 12 and 13). The compiler will use the
partially specialized template if both template arguments have the same
type. The partially specialized template, as opposed to the general template,
has only one type parameter.

Our reasoning for the class template remove_const is similar. The general
template returns, via its member type , exactly the same type; the partially
specialized template returns the new type after removing the const
property (line 22) The compiler will choose the partially specialized
https://www.educative.io/courses/generic-templates-in-cpp/m7Ny81pnZ5p 5/6
3/20/22, 6:17 PM Type-Traits Overview - Generic Programming Templates in C++
property (line 22). The compiler will choose the partially specialized
template if its template argument is const .

The rest is quickly explained. In lines 31 and 32, we used the functions of the
type-traits library and our own versions. We declared a typedef mydouble
(line 34), a type myString (line 37), and a type myInt (line 40). All types are
non-constant.

In the next lesson, we’ll study type-traits correctness and their optimization
with the help of an example.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solution Type-Traits (Correctness and Optimiza…

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/m7Ny81pnZ5p 6/6
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++

Type-Traits (Correctness and


Optimization)
In this lesson, we'll study type-traits correctness and their optimization using a gcd (greatest
common divisor) algorithm along with fill and equal (type-trait features).

We'll cover the following

• Correctness

• gcd - The First


• gcd - The Second

• gcd - The Third


• The Smaller Type

• The Common Type

• gcd - The Fourth


• Type-Traits: Performance
• Type-Traits fill
• Type-Traits std::equal

Correctness#
The reason we use type-traits is correctness and optimization. Let’s start
with correctness. The idea is to implement generic gcd algorithms, step by
step, to make it more type-safe with the help of the type-traits library.

gcd The First#


https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 1/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++
gcd - The First#

Our starting point is the euclid algorithm


(https://en.wikipedia.org/wiki/Greatest_common_divisor) to calculate the
greatest common divisor of two numbers.

It’s quite easy to implement the algorithm as a function template and feed it
with various arguments. Let’s start!

1 #include <iostream>
2
3 template<typename T>
4 T gcd(T a, T b){
5 if( b == 0 ) return a;
6   else return gcd(b, a % b);
7 }
8
9 int main(){ 
10   std::cout << gcd(100, 10) << std::endl;  // 10
11   std::cout << gcd(100, 33) << std::endl;  // 1
12   std::cout << gcd(100, 0) << std::endl;   // 100
13   std::cout << gcd(3.5, 4.0) << std::endl; // ERROR
14   std::cout << gcd("100", "10") << std::endl;  // ERROR
15   std::cout << gcd(100, 10L) << std::endl;  // ERROR
16 }

Output 1.35s

main.cpp: In function 'int main()':

main.cpp:15:28: error: no matching function for call to 'gcd(int, long int)'

15 | std::cout << gcd(100, 10L) << std::endl; // ERROR

| ^

main.cpp:4:3: note: candidate: 'template<class T> T gcd(T, T)'

4 | T gcd(T a, T b){

| ^~~

main.cpp:4:3: note: template argument deduction/substitution failed:

main.cpp:15:28: note: deduced conflicting types for parameter 'T' ('int'


https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 2/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++
main.cpp:15:28: note: deduced conflicting types for parameter T ( int
and 'long int')

15 | std::cout << gcd(100, 10L) << std::endl; // ERROR

| ^

main.cpp: In instantiation of 'T gcd(T, T) [with T = double]':

main.cpp:13:28: required from here

main.cpp:6:24: error: invalid operands of types 'double' and 'double' to


binary 'operator%'

6 | else return gcd(b, a % b);

| ~~^~~

main.cpp: In instantiation of 'T gcd(T, T) [with T = const char*]':

main.cpp:14:31: required from here

main.cpp:6:24: error: invalid operands of types 'const char*' and 'const


char*' to binary 'operator%'

The function template has two serious issues.

First, it is too generic. The function template accepts doubles (line 13)
and C strings (line 14). But it makes no sense to determine the greatest
common divisor of both data types. The modulo operation ( % ) for the
double and the C string values fails in line 6. But that’s not the only
issue.
Second, gcds depend on one type parameter, T . This shows the function
template signature gcd(T a, T b)) . a and b have to be of the same
type T . There is no conversion for type parameters. Therefore, the
instantiation of gcd with an int type and a long type (line 15) fails.

gcd - The Second#


We can ignore the rest of the examples below where both arguments have to
be positive numbers. The static_assert operator and the predicate
std::is_integral<T>::value will help us to check at compile-time whether T
is an integral type. A predicate always returns a boolean value.

1 #include <iostream>
2 #include <type_traits>
3
https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 3/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++
3
4 template<typename T>
5 T gcd(T a, T b){
6   static_assert(std::is_integral<T>::value, "T should be integral type!");
7   if( b == 0 ) return a;
8   else return gcd(b, a % b);
9 }
10 int main(){
11   std::cout << gcd(3.5, 4.0) << std::endl;
12   std::cout << gcd("100", "10") << std::endl;
13 }  

Output 1.26s

main.cpp: In instantiation of 'T gcd(T, T) [with T = double]':

main.cpp:11:28: required from here

main.cpp:6:38: error: static assertion failed: T should be integral type!

6 | static_assert(std::is_integral<T>::value, "T should be integral


type!");

| ^~~~~

main.cpp:8:24: error: invalid operands of types 'double' and 'double' to


binary 'operator%'

8 | else return gcd(b, a % b);

| ~~^~~

main.cpp: In instantiation of 'T gcd(T, T) [with T = const char*]':

main.cpp:12:31: required from here

main.cpp:6:38: error: static assertion failed: T should be integral type!

6 | static_assert(std::is_integral<T>::value, "T should be integral


type!");

| ^~~~~

main.cpp:8:24: error: invalid operands of types 'const char*' and 'const


char*' to binary 'operator%'

8 | else return gcd(b, a % b);

| ~~^~~

Great. We have solved the first issue of the gcd algorithm. The compilation
will not fail by accident because the modulo operator is not defined for a
double value and a C string The compilation fails because the assertion in
https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 4/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++
double value and a C string. The compilation fails because the assertion in

line 6 will not hold true. The subtle difference is that we now get an exact
error message and not a cryptic output of a failed template instantiation as
in the first example.

But what about the second issue. The gcd algorithm should accept
arguments of a different type.

gcd - The Third#


That’s no big deal. But wait, what should the type of result be?

1 #include <iostream>
2 #include <type_traits>
3
4 template<typename T1, typename T2> 
5 ??? gcd(T1 a, T2 b){
6   static_assert(std::is_integral<T1>::value, "T1 should be integral!");
7   static_assert(std::is_integral<T2>::value, "T2 should be integral!");
8   if( b == 0 ) 
9     return a;
10   else 
11     return gcd(b, a % b);
12 }
13
14 int main(){
15   std::cout << gcd(100, 10L) << std::endl;
16 }

The three questions marks in line 5 show the core of the issue. Should the
first type or the second type be the return type of the algorithm? Or should
the algorithm derive a new type from the two arguments? The type-traits
library comes to the rescue. We will present two variations.

The Smaller Type#


https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 5/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++

A good choice for the return type is to use the smaller of both types.
Therefore, we need a ternary operator at compile-time. Thanks to the type-
traits library, we have it. The ternary function std::conditional operates on
types and not on values. That’s because we apply the function at compile-
time. So, we have to feed std::conditional with the right constant
expression and we are done. std::conditional<(sizeof(T1) < sizeof(T2)),
T1, T2>::type will return, at compile-time, T1 if T1 is smaller than T2 ; it
will return T2 if T2 is not smaller than T1 .

Let’s apply the logic.

1 #include <iostream>
2 #include <type_traits>
3 #include <typeinfo>
4 template<typename T1, typename T2>
5 typename std::conditional<(sizeof(T1)<sizeof(T2)),T1,T2>::type gcd(T1 a, T2 b){
6   static_assert(std::is_integral<T1>::value, "T1 should be integral!");
7   static_assert(std::is_integral<T2>::value, "T2 should be integral!");
8   if( b == 0 )
9     return a;
10   else
11     return gcd(b, a % b);
12 }
13
14 int main(){
15   std::cout << gcd(100,10LL) << std::endl;
16   auto res= gcd(100,10LL);
17   std::conditional<(sizeof(long long)<sizeof(long)), long long, long>::type res2=gcd
18   std::cout << typeid(res).name() << std::endl;  // i 
19   std::cout << typeid(res2).name() << std::endl; // l 
20   std::cout << std::endl;
21 }

https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 6/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++

Output 1.55s

10

The critical line of the program is in line 5 with the return type of the gcd
algorithm. Of course, the algorithm can also deal with template arguments
of the same type. What about line 15? We used the number 100 of type int
and the number 10 of type long long int . The result for the greatest
common divisor is 10. Line 17 is extremely ugly. We have to repeat the
expression std::conditional <(sizeof(100) < sizeof(10LL)), long long,
long>::type to determine the right type of the variable res2 . Automatic type
deduction with auto comes to my rescue (line 16). The typeid operator in
line 18 and 19 shows that the result type of the arguments of type int and
long long int is int ; that the result type of the types long long int and
long int is long int .

The Common Type#


Now to the second variation. Often it is not necessary to determine the
smaller type at compile-time but to determine the type to which all types can
implicitly be converted to. std::common_type can handle an arbitrary
number of template arguments. To say it more formally. std::common_type is
a variadic template
(https://www.educative.io/collection/page/10370001/5799373671759872/4774
034837340160).

1 #include <iostream>
2 #include <type traits>
https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 7/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++
2 #include <type_traits>
3 #include <typeinfo>
4
5 template<typename T1, typename T2>
6 typename std::common_type<T1, T2>::type gcd(T1 a, T2 b){
7   static_assert(std::is_integral<T1>::value, "T1 should be an integral type!");
8   static_assert(std::is_integral<T2>::value, "T2 should be an integral type!");
9   if( b == 0 ){
10     return a;
11   }
12   else{
13     return gcd(b, a % b);
14   }
15 }
16 int main(){
17   std::cout << typeid(gcd(100, 10)).name() << std::endl;  // i 
18   std::cout << typeid(gcd(100, 10L)).name() << std::endl;  // l 
19   std::cout << typeid(gcd(100, 10LL)).name() << std::endl;  // x
20  }

Output 1.45s

The only difference to the last implementation is that std::common_type in


line 6 determines the return type. We ignored the results of the gcd
algorithm in this example because we’re more interested in the types of
results. With the argument types int and int we get int ; with the
argument types int and long int we get long int , and with int and long
long int we get long long int .

gcd - The Fourth#


https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 8/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++

But that’s not all. std::enable_if from the type-traits library provides a very
interesting variation. What the previous implementations have in common
is that they will check in the function body if the arguments are of integral
types or not. The key observation is that the compiler always tries to
instantiate the function templates but sometimes fails. We know the result.
If the expression std::is_integral returns false , the instantiation will fail.
That is not the best way. It would be better if the function template is only
available for the valid types. Therefore, we put the check of the function
template from the template body to the template signature.

1 #include <iostream>
2 #include <type_traits>
3
4 template<typename T1, typename T2,
5   typename std::enable_if<std::is_integral<T1>::value,T1 >::type= 0,
6   typename std::enable_if<std::is_integral<T2>::value,T2 >::type= 0, 
7   typename R = typename std::conditional<(sizeof(T1) < sizeof(T2)),T1,T2>::type>
8 R gcd(T1 a, T2 b){
9   if( b == 0 ){ 
10     return a; 
11   } 
12   else{
13     return gcd(b, a % b);
14   }
15 }
16
17 int main(){
18   std::cout << "gcd(100, 10)= " << gcd(100, 10) << std::endl; 
19   std::cout << "gcd(100, 33)= " << gcd(100, 33) << std::endl; 
20   std::cout << "gcd(3.5, 4.0)= " << gcd(3.5, 4.0) << std::endl;
21 }

https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 9/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++

Output 1.99s

main.cpp: In function 'int main()':

main.cpp:20:49: error: no matching function for call to 'gcd(double, double)'

20 | std::cout << "gcd(3.5, 4.0)= " << gcd(3.5, 4.0) << std::endl;

| ^

main.cpp:8:3: note: candidate: 'template<class T1, class T2, typename


std::enable_if<std::is_integral<_Tp>::value, T1>::type <anonymous>, typename
std::enable_if<std::is_integral<T2>::value, T2>::type <anonymous>, class R> R
gcd(T1, T2)'

8 | R gcd(T1 a, T2 b){

| ^~~

main.cpp:8:3: note: template argument deduction/substitution failed:

main.cpp:5:67: error: no type named 'type' in 'struct std::enable_if<false,


double>'

5 | typename std::enable_if<std::is_integral<T1>::value,T1 >::type= 0,

| ^

Lines 5 and 6 are the key lines of the new program. The expression
std::is_integral determines whether the type parameter T1 and T2 are
integrals. If T1 and T2 are not integrals, and therefore they return false ,
we will not get a template instantiation. This is the decisive observation.

If std::enable_if returns true as the first parameter, std::enable_if will


have a public member typedef type. This type is used in lines 5 and 6. If
std::enable_if returns false as first parameter, std::enable_if will have
no member type . Therefore, lines 5 and 6 are not valid. This is not an error
but a common technique in C++: SFINAE
(https://en.cppreference.com/w/cpp/language/sfinae). SFINAE stands for
Substitution Failure Is Not An Error. Only the template for exactly this type
will not be instantiated and the compiler tries to instantiate the template in
another way.

Type-Traits: Performance#

https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 10/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++

The idea is quite straightforward and is used in current implementations of


the Standard Template Library (STL). If the elements of a container are
simple enough, the algorithm of the STL like std::copy , std::fill , or
std::equal will directly be applied on the memory area. Instead of using
std::copy to copy the elements one by one, all is done in one step. Internally,
C functions like memcmp , memset , memcpy , or memmove are used. The small
difference between memcpy and memmove is that memmove can deal with
overlapping memory areas.

The implementations of the algorithm std::copy , std::fill , or std::equal


use a simple strategy. std::copy is like a wrapper. This wrapper checks if the
element is simple enough. If so, the wrapper will delegate the work to the
optimized copy function. If not, the general copy algorithm will be used. This
one copies each element after one another. To make the right decision, the
functions of the type-traits library will be used if the elements are simple
enough.

The graphic shows this strategy once more:

https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 11/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++

Type-Traits: Optimization

Type-Traits fill #
std::fill assigns each element, in the range, a value. The listing shows a
simple implementation which is based on the GCC implementation.

1 // fill.cpp
2  
3 #include <cstring>
4 #include <chrono>
5 #include <iostream>
6 #include <type_traits>
7
8 namespace my{
9 (/learn)
10   template <typename I, typename T, bool b>
11   void fill_impl(I first, I last, const T& val, const std::integral_constant<bool, b
12     while(first != last){
13       *first = val;
14       ++first;
15     }
https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 12/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++
15     }
16   }
17
18   template <typename T>
19   void fill_impl(T* first, T* last, const T& val, const std::true_type&){
20     std::memset(first, val, last-first);
21   }
22
23   template <class I, class T>
24   inline void fill(I first, I last, const T& val){
25     // typedef std::integral_constant<bool,std::has_trivial_copy_assign<T>::value &&
26     typedef std::integral_constant<bool,std::is_trivially_copy_assignable<T>::value 
27     fill_impl(first, last, val, boolType());
28   }
29 }
30
31 const int arraySize = 100000000;
32 char charArray1[arraySize]= {0,};
33 char charArray2[arraySize]= {0,};
34
35 int main(){
36
37   std::cout << std::endl;
38
39   auto begin= std::chrono::system_clock::now();
40   my::fill(charArray1, charArray1 + arraySize,1);
41   auto last=  std::chrono::system_clock::now() - begin;
42   std::cout <<  "charArray1: " << std::chrono::duration<double>(last).count() << " s
43
44   begin= std::chrono::system_clock::now();
45   my::fill(charArray2, charArray2 + arraySize, static_cast<char>(1));
46   last=  std::chrono::system_clock::now() - begin;
47   std::cout <<  "charArray2: " << std::chrono::duration<double>(last).count() << " s
48
49   std::cout << std::endl;
50
51 }

Output 2.35s

charArray1: 0.494381 seconds

charArray2: 0.0582584 seconds

https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 13/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++

my::fill make in line 27 the decision which implementation of


my::fill_impl is applied. To use the optimized variant, the elements should
have a compiler generated copy assignment operator
std::is_trivially_copy_assignable<T> and should be 1 byte large: sizeof(T)
== 1 . The function std::is_trivially_copy_assignable is part of the type-
traits library. The first call my::fill(charArray1, charArray1 + arraySize,1);
has the last parameter 1, which is an int that has a size of 4 bytes. That is
why, the test on line 26 evaluates to false.

Our GCC calls the function std::is_trivially_copy_assignable instead of


std::has_trivial_copy_assign . If we request with the keyword default from
the compiler the copy assignment operator, the operator will be trivial.

Type-Traits std::equal #
The following code snippet shows a part of the implementation of
std::equal in the GCC:

1 template<typename _II1, typename _II2>
2 inline bool __equal_aux(_II1 __first1, _II1 __last1, _II2 __first2){
3   typedef typename iterator_traits<_II1>::value_type _ValueType1; 
4   typedef typename iterator_traits<_II2>::value_type _ValueType2; 
5   const bool __simple = ((__is_integer<_ValueType1>::__value
6                          || __is_pointer<_ValueType1>::__value )
7                          && __is_pointer<_II1>::__value
8                          && __is_pointer<_II2>::__value 
9                          &&__are_same<_ValueType1, _ValueType2>::__value
10                         );
11 return std::__equal<__simple>::equal(__first1, __last1, __first2);
12 }

We have a different perception of __simple . To use the optimized variant of


std::equal , the container elements have to fulfill some assurances. The
elements of the container have to be of the same type (line 9) and have to be
https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 14/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++
elements of the container have to be of the same type (line 9) and have to be

an integral or a pointer (lines 5 and 6). In addition, the iterators have to be


pointers (lines 7 and 8).

If you would like to learn about the type-traits library in more detail, the
chapter on Type Traits (https://www.educative.io/courses/cpp-standard-
library-including-cpp-14-and-cpp-17/7nA7550oor8) in our course C++
Standard Library including C++ 14 & C++ 17
(https://www.educative.io/courses/cpp-standard-library-including-cpp-14-
and-cpp-17) is a great place to start.

In the next lesson, we’ll look at a couple of examples of type traits.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Type-Traits Overview - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 15/16
3/20/22, 6:19 PM Type-Traits (Correctness and Optimization) - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/qA1OYzn7nn0 16/16
3/20/22, 6:20 PM - Examples - Generic Programming Templates in C++

- Examples
Let's have a look at a couple of examples of type-traits.

We'll cover the following

• Example 1: Template fill

• Explanation
• Example 2: Template Type Manipulation

• Explanation

Example 1: Template fill#


1 // templatefill.cpp
2  
3 #include <cstring>
4 #include <chrono>
5 #include <iostream>
6 #include <type_traits>
7
8 namespace my{
9
10   template <typename I, typename T, bool b>
11   void fill_impl(I first, I last, const T& val, const std::integral_constant<bool, b
12     while(first != last){
13       *first = val;
14       ++first;
15     }
16   }
17
18   template <typename T>
19   void fill_impl(T* first, T* last, const T& val, const std::true_type&){
20     std::memset(first, val, last-first);
21   }
22
23 template <class I class T>
https://www.educative.io/courses/generic-templates-in-cpp/mE9MYGjx5R0 1/5
3/20/22, 6:20 PM - Examples - Generic Programming Templates in C++
23   template <class I, class T>
24   inline void fill(I first, I last, const T& val){
25     typedef std::integral_constant<bool,std::is_trivially_copy_assignable<T> ::value
26     fill_impl(first, last, val, boolType());
27   }
28 }
29
30 const int arraySize = 100000000;
31 char charArray1[arraySize]= {0,};
32 char charArray2[arraySize]= {0,};
33
34 int main(){
35
36   std::cout << std::endl;
37
38   auto begin= std::chrono::system_clock::now();
39   my::fill(charArray1, charArray1 + arraySize, 1);
40   auto last=  std::chrono::system_clock::now() - begin;
41   std::cout <<  "charArray1: " << std::chrono::duration<double>(last).count() << " s
42
43   begin= std::chrono::system_clock::now();
44   my::fill(charArray2, charArray2 + arraySize, static_cast<char>(1));
45   last=  std::chrono::system_clock::now() - begin;
46   std::cout <<  "charArray2: " << std::chrono::duration<double>(last).count() << " s
47
48   std::cout << std::endl;
49
50 }
51

Output 2.15s

charArray1: 0.432327 seconds

charArray2: 0.053552 seconds

Explanation#
In line 26, my::fill make the decision as to which implementation of
i li d T th
https://www.educative.io/courses/generic-templates-in-cpp/mE9MYGjx5R0 ti i d i t th l t h ld 2/5
3/20/22, 6:20 PM - Examples - Generic Programming Templates in C++

my::fill_impl is applied. To use the optimized variant, the elements should


have a compiler generated copy assignment operator
std::is_trivially_copy_assignable<T> and should be 1 byte large: sizeof(T)
== 1 . The function std::is_trivially_copy_assignable is part of the type-
traits library.

If the expression boolType() in line 26 is true, the optimized version of


my::fill_impl in the lines 17 - 20 will be used. This variant fills in opposite
of the generic variant my::fill_impl (line 10-16) the entire memory area -
consisting of 100 million entries - with the value 1. sizeof(char) is 1.

What’s about the performance of the program? We compiled the program


(/learn)
with full optimization. The execution of the optimized variant is about 3
times faster on windows; about 20 times faster on Linux.

Example 2: Template Type


Manipulation#
1 // templateTypeManipulation.cpp
2
3 #include <iostream>
4 #include <type_traits>
5
6 template <typename T>
7 struct RemoveConst{
8     typedef T type;
9 };
10
11 template <typename T>
12 struct RemoveConst<const T>{
13     typedef T type;
14 };
15
16
17 int main(){
18
19     std::cout << std::boolalpha << std::endl;
20
21     std::cout << "std::is_same<int, RemoveConst<int>::type>::value: " << std::is_sam
22 td t " td i i t R
https://www.educative.io/courses/generic-templates-in-cpp/mE9MYGjx5R0
C t t i t t l " td3/5
3/20/22, 6:20 PM - Examples - Generic Programming Templates in C++
22     std::cout << "std::is_same<int, RemoveConst<const int>::type>::value: " << std::
23     
24     std::cout << std::endl;
25  
26 }
27

Output 2.01s

std::is_same<int, RemoveConst<int>::type>::value: true

std::is_same<int, RemoveConst<const int>::type>::value: true

Explanation#
The code above uses the function std::is_same from the type-traits
library. std::is_same compares the type passed in the function and the type
given in the function defined by us, and it returns true only when both
types are the same.

In the next lesson, we’ll solve exercise on type-traits.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022
https://www.educative.io/courses/generic-templates-in-cpp/mE9MYGjx5R0 4/5
3/20/22, 6:20 PM - Examples - Generic Programming Templates in C++

Back Next

Type-Traits (Correctness and Optimiza… - Exercise

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/mE9MYGjx5R0 5/5
3/20/22, 6:21 PM - Exercise - Generic Programming Templates in C++

- Exercise
Let's solve an exercise in this lesson.

We'll cover the following

• Problem Statement

Problem Statement#
Get used to the many functions of the type traits library.

The objective of this exercise is to get familiar with the type-traits library.
What we want to achieve here is to modify an int type by doing a, b, c and
d.

Modify an int type at compile-time.


(/learn)
Add const to it.

Remove const from it.


Compare it with a const int .

1 #include <iostream>
2 #include <type_traits>
3
4 int main() {
5   // Write different functions of type traits here
6   std::cout << "";
7 }

https://www.educative.io/courses/generic-templates-in-cpp/3j44PVqNJwn 1/2
3/20/22, 6:21 PM - Exercise - Generic Programming Templates in C++

Let’s move on to the solution to this exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Examples - Solution

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/3j44PVqNJwn 2/2
3/20/22, 6:22 PM - Solution - Generic Programming Templates in C++

- Solution
Let's have a look at the solution to the previous exercise in this lesson.

We'll cover the following

• Solution Review

• Explanation

Solution Review#
1 // templateTypeTraitsModifications.cpp
2
3 #include <iostream>
4 #include <type_traits>
5
6 int main(){
7
8   std::cout << std::boolalpha << std::endl;
9
10   std::cout << "std::is_const<std::add_const<int>::type>::value: " <<  std::is_const
11   std::cout << "std::is_const<std::remove_const<const int>::type>::value: " << std::
12
13   std::cout << std::endl;
14   typedef std::add_const<int>::type myConstInt;
15   std::cout << "std::is_const<myConstInt>::value: " << std::is_const<myConstInt>::va
16   typedef const int myConstInt2;
17   std::cout << "std::is_same<myConstInt, myConstInt2>::value: " << std::is_same<myCo
18
19   std::cout << std::endl;
20
21   int fir= 1;
22   int& refFir1= fir;
23   using refToIntType= typename std::add_lvalue_reference<int>::type;
24   refToIntType refFir2= fir;
25
26   std::cout << "(fir, refFi1r, refFir2): "  << "(" << fir << ", " << refFir1 << ", "
https://www.educative.io/courses/generic-templates-in-cpp/xV5Rm5YB9Zl 1/3
3/20/22, 6:22 PM - Solution - Generic Programming Templates in C++

27
28   fir= 2;
29
30   std::cout << "(fir, refFir1, refFir2): "  << "(" << fir << ", " << refFir1 << ", "
31
32   std::cout << std::endl;
33
34 }
35

Output 1.33s

std::is_const<std::add_const<int>::type>::value: true

std::is_const<std::remove_const<const int>::type>::value: false

std::is_const<myConstInt>::value: true

std::is_same<myConstInt, myConstInt2>::value: true

(/learn)
(fir, refFi1r, refFir2): (1, 1, 1)

(fir, refFir1, refFir2): (2, 2, 2)

Explanation#
Lines 10 and 11 determine at compile-time if the manipulated type is const .
myConstInt is a type alias for an const int . Line 17 shows, with the help of
the function std::is_same , that myConstInt and myConstInt2 are the same
types. An lvalue such as fir can only be bound to an lvalue reference . Line
24 shows this in a complicated way. Line 26 proves that refFir1 and
refFire2 are references.

In the next lesson, we’ll discuss constexpr.

https://www.educative.io/courses/generic-templates-in-cpp/xV5Rm5YB9Zl 2/3
3/20/22, 6:22 PM - Solution - Generic Programming Templates in C++

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise constexpr

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/xV5Rm5YB9Zl 3/3
3/20/22, 6:22 PM constexpr - Generic Programming Templates in C++

constexpr
In this lesson, we'll study constexpr.

We'll cover the following

• Constant Expressions

• constexpr - Variables and Objects


• Variables

• User-Defined Types
• Example

• Functions

• Examples
• Functions with C++14
• constexpr Functions in C++14
• Example

• Template Metaprogramming vs constexpr Functions

Constant Expressions#
You can define, with the keyword constexpr , an expression that can be
evaluated at compile-time. constexpr can be used for variables, functions,
and user-defined types. An expression that is evaluated at compile-time has
a lot of advantages.
A constant expression

can be evaluated at compile-time.

gives the compiler deep insight into the code


https://www.educative.io/courses/generic-templates-in-cpp/B6WpXmVMY0N 1/8
3/20/22, 6:22 PM constexpr - Generic Programming Templates in C++
gives the compiler deep insight into the code.
is implicitly thread-safe.

constexpr - Variables and Objects#


If you declare a variable as constexpr , the compiler will evaluate them at
compile-time. This holds not only true for built-in types but also for
instantiations of user-defined types. There are a few serious restrictions for
objects in order to evaluate them at compile-time.

To make life easier for us, we will call the C types like bool , char , int , and
double primitive data types. We will call the remaining data types as user-
defined data types. These are for example, std::string , types from the C++
library and non-primitive data types. Non-primitive data types typically hold
primitive data types.

Variables#
By using the keyword constexpr , the variable becomes a constant
expression.

constexpr double pi= 3.14;

Therefore, we can use the variable in contexts that require a constant


expression. For example, if we want to define the size of an array. This has to
be done at compile-time.

For the declaration of a constexpr variable, you have to keep a few rules in
mind.

The variable:

is implicitly const.

has to be initialized.
requires a constant expression for initialization.
https://www.educative.io/courses/generic-templates-in-cpp/B6WpXmVMY0N 2/8
3/20/22, 6:22 PM q p constexpr - Generic Programming Templates in C++

The above rules make sense because if we evaluate a variable at compile-


time, the variable can only depend on values that can be evaluated at
compile time.

The objects are created by the invocation of the constructor and the
constructor has a few special rules as well.

User-Defined Types#
A constexpr constructor

1. can only be invoked with constant expressions.


2. cannot use exception handling.

3. has to be declared as default or delete or the function body must be


empty (C++11).

The constexpr user-defined type

cannot have virtual base classes.


requires that each base object and each non-static member has to be
initialized in the initialization list of the constructor or directly in the
class body. Consequently, it holds that each used constructor (e.g of a
base class) has to be a constexpr constructor and that the applied
initializers have to be constant expressions.

Example#
struct MyDouble{

  double myVal;

  constexpr MyDouble(double v): myVal(v){} 

  constexpr double getVal(){return myVal;}

};

https://www.educative.io/courses/generic-templates-in-cpp/B6WpXmVMY0N 3/8
3/20/22, 6:22 PM constexpr - Generic Programming Templates in C++

The constructor has to be empty and a constant expression.

The user-defined type can have methods which are constant


expressions and cannot to be virtual .
Instances of MyDouble can be instantiated at compile-time.

Functions#
constexpr functions are functions that have the potential to run at compile-
time. With constexpr functions, you can perform a lot of calculations at
compile-time. Therefore, the result of the calculation is available at runtime
and stored as a constant in the ROM available. In addition, constexpr
functions are implicitly inline.

A constexr function can be invoked with a non- constexpr value. In this


case, the function runs at runtime. A constexpr function is executed at
compile-time when it is used in an expression which is evaluated at compile-
time. Some examples would be when using a static_assert or the definition
of a C-array. A constexpr function is also executed at compile-time, when the
result is requested at compile-time, for example: constexpr auto res =
constexprFunction() .

For constexpr functions there are a few restrictions:

The function

has to be non-virtual.

has to have arguments and a return value of a literal type


(https://en.cppreference.com/w/cpp/named_req/LiteralType). Literal
types are the types of constexpr variables.

can only have one return statement.

must return a value.


https://www.educative.io/courses/generic-templates-in-cpp/B6WpXmVMY0N 4/8
3/20/22, 6:22 PM constexpr - Generic Programming Templates in C++

will be executed at compile-time if invoked within a constant


expression.

can only have a function body consisting of a return statement.

must have a constant return value

is implicitly inline.

Examples#
constexpr int fac(int n){

   return n > 0 ? n * fac(n-1): 1;

constexpr int gcd(int a, int b){
  return (b==0) ? a : gcd(b, a % b);

Functions with C++14#


The syntax of constexpr functions was massively improved with the change
from C++11 to C++14. In C++11, you had to keep in mind which feature you
can use in a constexpr functions. With C++14, you only have to keep in mind
which feature you can’t use in a constexpr function.

constexpr Functions in C++14#


can have variables that have to be initialized by a constant expression.

cannot have static or thread_local data.

can have conditional jump instructions or loop instructions.


can have more than one instruction.
https://www.educative.io/courses/generic-templates-in-cpp/B6WpXmVMY0N 5/8
3/20/22, 6:22 PM constexpr - Generic Programming Templates in C++

Example#
1 constexpr auto gcd(int a, int b){
2   while (b != 0){
3     auto t= b;
4     b= a % b;
5     a= t;
6 (/learn)
  }
7   return a;
8 }

Template Metaprogramming vs
constexpr Functions#

Template Constant
Characteristics
Metaprogramming Expressions

Compile-time and
Execution time Compile-time
runtime

Arguments Types and values Values

Programming
Functional Imperative
paradigm

Modification No Yes

Control structure Recursion Conditions and Loops

https://www.educative.io/courses/generic-templates-in-cpp/B6WpXmVMY0N 6/8
3/20/22, 6:22 PM constexpr - Generic Programming Templates in C++

Template Constant
Characteristics
Metaprogramming Expressions

Conditional Template Conditional


execution specialization statement

There are a few remarks about the above-mentioned table.

A template metaprogram runs at compile-time, but a constexpr


functions can run at compile-time or runtime.

Arguments of a template (template metaprogram) can be types and


values. To be more specific, a template can take types,
std::vector<int> , values, std::array<int, 5> , and even templates
std::stack<int, std::vector<int>> . constexpr functions are just
functions which have the potential to run at compile time. Therefore,
they can only accept values.

To learn more about constexpr , click here


(https://en.cppreference.com/w/cpp/language/constexpr).

In the next lesson, we’ll look at a couple of examples of constexpr .

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

https://www.educative.io/courses/generic-templates-in-cpp/B6WpXmVMY0N 7/8
3/20/22, 6:22 PM constexpr - Generic Programming Templates in C++

Back Next

- Solution - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/B6WpXmVMY0N 8/8
3/20/22, 6:23 PM - Examples - Generic Programming Templates in C++

- Examples
In this lesson, we'll get into examples of constexpr.

We'll cover the following

• Example 1: constexpr using C++ 11

• Explanation
• Example 2: constexpr function in C++ 14

• Explanation

Example 1: constexpr using C++ 11#


1 // constExpression.cpp
2
3 #include <iostream>
4
5 constexpr int square(int x) { return x * x; }
6 constexpr int squareToSquare(int x){ return square(square(x));}
7
8 int main() {
9
10   std::cout << std::endl;
11
12   static_assert(square(10) == 100, "you calculated it wrong");
13   static_assert(squareToSquare(10) == 10000 , "you calculated it wrong");
14
15   std::cout<< "square(10)= " << square(10) << std::endl;
16   std::cout<< "squareToSquare(10)= " << squareToSquare(10) << std::endl;
17   constexpr int constExpr= square(10);
18
19   int arrayClassic[100];
20   int arrayNewWithConstExpression[constExpr];
21   int arrayNewWithConstExpressioFunction[square(10)];
22
23 std::cout << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/B6A6X18AY6Q 1/5
3/20/22, 6:23 PM - Examples - Generic Programming Templates in C++
23   std::cout << std::endl;
24
25 }
26

Output 1.54s

square(10)= 100

squareToSquare(10)= 10000

Explanation#
In the example above, we have implemented two constexpr functions:
constexpr int square(int x) and constexpr int squareToSquare(int x) .
As you can see, both the functions follow the conventions for constexpr
functions definition in C++11.

The assertion in lines 12 and 13 succeed since 10 is a literal type.


Making a constexpr variable will allow the code compilation to pass the
assertions.

In line 17, we have initialized a constexpr variable constExpr using the


sqaure function.

In lines 19-21, we have initialized three arrays

1. by using a constant 100

2. by using a constexpr variable constExpr


https://www.educative.io/courses/generic-templates-in-cpp/B6A6X18AY6Q 2/5
3/20/22, 6:23 PM - Examples - Generic Programming Templates in C++

3. by calling the function square(10) . Notice that the input argument


for this function call is constant.

Example 2: constexpr function in C++


14#
1 // constExpressionCpp14.cpp
2
3 #include <iostream>
4
5 constexpr int gcd(int a, int b){
6   while (b != 0){
7     auto t= b;
8     b= a % b;
9     a= t;
10   }
11   return a;
12 }
13
14 int main(){
15
16   std::cout << std::endl;
17
18   constexpr auto res= gcd(100, 10);
19   std::cout << "gcd(100, 10) " << res << std::endl;
20
21   auto val= 100;
22   auto res2= gcd(val, 10);
23   std::cout << "gcd(val, 10) " << res2 << std::endl;
24
25 }
26

(/learn)

https://www.educative.io/courses/generic-templates-in-cpp/B6A6X18AY6Q 3/5
3/20/22, 6:23 PM - Examples - Generic Programming Templates in C++

Output 1.7s

gcd(100, 10) 10

gcd(val, 10) 10

Explanation#
Line 18 calculates the result res at compile-time, and line 22 res2 at
runtime.

The difference between ordinary functions and constexpr functions in


C++14 is minimal. Therefore, it’s quite easy to implement the gcd
algorithm in C++14 as a constexpr function.

We have defined res as constexpr variable and its type is


automatically determined by auto .

We’ll solve an exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

constexpr - Exercise

Mark as Completed
https://www.educative.io/courses/generic-templates-in-cpp/B6A6X18AY6Q 4/5
3/20/22, 6:23 PM - Examples - Generic Programming Templates in C++
Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/B6A6X18AY6Q 5/5
3/20/22, 6:24 PM - Exercise - Generic Programming Templates in C++

- Exercise
Let's solve an exercise in this lesson.

We'll cover the following

• Try It Out!

Try It Out!#
Use my MyDouble in your program.

How can you be sure that instances of MyDouble are created at compile
time?
What happens, if the instances of my MyDouble are used in non-
constexpr contexts?
(/learn)
1 #include <iostream>
2
3 struct MyDouble{
4   double myVal;
5   constexpr MyDouble(double v): myVal(v){}
6   constexpr double getVal(){
7     return myVal; 
8   } 
9 };
10
11 int main() {
12   // try to call non-constexpr myDouble instance
13 }

https://www.educative.io/courses/generic-templates-in-cpp/R8KXJAAPoZq 1/2
3/20/22, 6:24 PM - Exercise - Generic Programming Templates in C++

In the next lesson, we’ll study constexpr if .

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Examples constexpr if

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/R8KXJAAPoZq 2/2
3/20/22, 6:24 PM constexpr if - Generic Programming Templates in C++

(/learn)

constexpr if
Let's study constexpr if in this lesson.

We'll cover the following

• constexpr if (C++17)

constexpr if (C++17)#
constexpr if enables us to compile source code
conditionally.

if constexpr (cond) statement1;

else statement2;

The expression cond has to be a constant expression.

The unused code has to be valid.


Thanks to constexpr if , functions can have different return types.

The following code snippet shows a function, which returns an int or a


double .

template <typename T>

auto getAnswer(T t){

  static_assert(std::is_arithmetic_v<T>); // arithmetic

  if constexpr (std::is_integral_v<T>)    // integral

    return 42;

  else                                    

    return 42.0;        // floating point

https://www.educative.io/courses/generic-templates-in-cpp/qV77XBZBAGR 1/2
3/20/22, 6:24 PM constexpr if - Generic Programming Templates in C++

constexpr if is a replacement for tag dispatch and SFINAE


(https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error). SFINAE
stands for Substitution Failure Is Not An Error.

To study further about tag dispatching, click here


(https://www.educative.io/collection/page/10370001/5799373671759872/5925
792309575680).

In the next lesson, we’ll look at an example of constexpr if .

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise - Example

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qV77XBZBAGR 2/2
3/20/22, 6:25 PM - Example - Generic Programming Templates in C++

- Example
Let's have a look at an example of constexpr if.

We'll cover the following

• Example: constexpr if

• Explanation

Example: constexpr if #
1 // constexprIf.cpp
2
3 #include <iostream>
4 #include <type_traits>
5
6 // SFINAE
7
8 template <typename T, std::enable_if_t<std::is_arithmetic<T>{}>* = nullptr>
9 auto get_value_SFINAE(T) {
10     std::cout << "get_Value_SFINAE(5)" << std::endl;
11 }
12
13 template <typename T, std::enable_if_t<!std::is_arithmetic<T>{}>* = nullptr>
14 auto get_value_SFINAE(T) {
15     std::cout << "get_Value_SFINAE(five)" << std::endl;
16
17 }
18
19 // Tag dispatch
20
21 template <typename T>
22 auto get_value_TAG_DISPATCH(T, std::true_type) {
23      std::cout << "get_Value_TAG_DISPATCH(5)" << std::endl;
24 }
25
26 template <typename T>
https://www.educative.io/courses/generic-templates-in-cpp/7XPOJYAKrgQ 1/4
3/20/22, 6:25 PM - Example - Generic Programming Templates in C++
27 auto get_value_TAG_DISPATCH(T, std::false_type) {
28     std::cout << "get_Value_TAG_DISPATCH(five)" << std::endl;
29 }
30
31 template <typename T>
32 auto get_value_TAG_DISPATCH(T t) {
33     return get_value_TAG_DISPATCH(t, std::is_arithmetic<T>{});
34 }
35
36 // constexpr if
37
38 template <typename T>
39 auto get_value_CONSTEXPR_IF(T) {
40      if constexpr (std::is_arithmetic_v<T>) {
41          std::cout << "get_Value_CONSTEXPR_IF(5)" << std::endl;
42      }
43      else {
44          std::cout << "get_Value_CONSTEXPR_IF(five)" << std::endl;
45      }
46 }
47
48 int main(){
49     
50     std::cout << std::endl;
51     
52     get_value_SFINAE(5);
53     get_value_SFINAE("five");
54     
55     std::cout << std::endl;
56     
57     get_value_TAG_DISPATCH(5);
58     get_value_TAG_DISPATCH("five");
59     
60     std::cout << std::endl;
61     
62     get_value_CONSTEXPR_IF(5);
63     get_value_CONSTEXPR_IF("five");
64     
65     std::cout << std::endl;
66 (/learn)
    
67 }
68

Output 1.83s

https://www.educative.io/courses/generic-templates-in-cpp/7XPOJYAKrgQ 2/4
3/20/22, 6:25 PM - Example - Generic Programming Templates in C++

get_Value_SFINAE(5)

get_Value_SFINAE(five)

get_Value_TAG_DISPATCH(5)

get_Value_TAG_DISPATCH(five)

get_Value_CONSTEXPR_IF(5)

get_Value_CONSTEXPR_IF(five)

Explanation#
We have created get_value functions which use SFINAE, TAG_DISPATCH,
and CONSTEXPR_IF. These functions use the std::is_arithmetic function
from the type-traits library. std::is_arithmetic returns true only if
std::is_integral or std::is_floating_point is true for a given type. All the
calls from main verify that the passed argument falls in their required
category.

get_value_SFINAE uses the function std::enable_if from the type-traits


library. std::enable_if is only true, if the given type is arithmetic.

get_value_TAG_DISPATCH in line 33 dispatches on the result of


std::is_arithmetic .

get_value_CONSTEXR_IF creates another branch of the if -statement


depending on the result of the expression std::is_arithmetic_v<T>
which is a shorthand for std::is_arithmetic<T>::value .

We have learned about the techniques which we used in templates. In the


next chapter, we’ll see different design techniques used in C++ Templates.

https://www.educative.io/courses/generic-templates-in-cpp/7XPOJYAKrgQ 3/4
3/20/22, 6:25 PM - Example - Generic Programming Templates in C++

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

constexpr if Static Versus Dynamic Polymorphism

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/7XPOJYAKrgQ 4/4
3/20/22, 6:26 PM Static Versus Dynamic Polymorphism - Generic Programming Templates in C++

(/learn)

Static Versus Dynamic Polymorphism


Let's dive deep into polymorphism in this lesson.

We'll cover the following

• Polymorphism

Polymorphism#
Polymorphism means that an object can have different behaviors.

Dynamic Polymorphism

Polymorphism happens at runtime.


A key feature of object-orientation.
Based on interfaces and virtual methods.
Needs one indirection such as a reference or a pointer in C++.

Static Polymorphism

Polymorphism happens at compile-time.


Is not bound to interfaces or derivation hierarchies => Duck Typing
(https://en.wikipedia.org/wiki/Duck_typing)
No indirection such as pointers or references required.
Static polymorphism is typically faster than dynamic
polymorphism.

https://www.educative.io/courses/generic-templates-in-cpp/xlGZgoMJoNE 1/2
3/20/22, 6:26 PM Static Versus Dynamic Polymorphism - Generic Programming Templates in C++

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Example - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/xlGZgoMJoNE 2/2
3/20/22, 6:28 PM - Examples - Generic Programming Templates in C++

- Examples
Let's have a look at a couple of examples of polymorphism.

We'll cover the following

• Example 1: Dispatch with Dynamic Polymorphism

• Explanation
• Example 2: Dispatch with Static Polymorphism

• Explanation

Example 1: Dispatch with Dynamic


Polymorphism#
1 // dispatchDynamicPolymorphism.cpp
2
3 #include <chrono>
4 #include <iostream>
5
6 auto start = std::chrono::steady_clock::now();
7
8 void writeElapsedTime(){
9     auto now = std::chrono::steady_clock::now();
10     std::chrono::duration<double> diff = now - start;
11   
12     std::cerr << diff.count() << " sec. elapsed: ";
13 }
14
15 struct MessageSeverity{                         
16     virtual void writeMessage() const {         
17         std::cerr << "unexpected" << std::endl;
18     }
19 };
20
https://www.educative.io/courses/generic-templates-in-cpp/m78xylop9wA 1/7
3/20/22, 6:28 PM - Examples - Generic Programming Templates in C++
20
21 struct MessageInformation: MessageSeverity{     
22     void writeMessage() const override {        
23         std::cerr << "information" << std::endl;
24     }
25 };
26
27 struct MessageWarning: MessageSeverity{         
28     void writeMessage() const override {        
29         std::cerr << "warning" << std::endl;
30     }
31 };
32
33 struct MessageFatal: MessageSeverity{};
34
35 void writeMessageReference(const MessageSeverity& messServer){
36     
37     writeElapsedTime();
38     messServer.writeMessage();
39     
40 }
41
42 void writeMessagePointer(const MessageSeverity* messServer){
43     
44     writeElapsedTime();
45     messServer->writeMessage();
46     
47 }
48
49 int main(){
50
51     std::cout << std::endl;
52   
53     MessageInformation messInfo;
54     MessageWarning messWarn;
55     MessageFatal messFatal;
56   
57     MessageSeverity& messRef1 = messInfo;            
58     MessageSeverity& messRef2 = messWarn;
59     MessageSeverity& messRef3 = messFatal;
60   
61     writeMessageReference(messRef1);              
62     writeMessageReference(messRef2);
63     writeMessageReference(messRef3);
64   
65     std::cerr << std::endl;
66   
67     MessageSeverity* messPoin1 = new MessageInformation;
68     MessageSeverity* messPoin2 = new MessageWarning;
69     MessageSeverity* messPoin3 = new MessageFatal;
70   
71     writeMessagePointer(messPoin1);               
https://www.educative.io/courses/generic-templates-in-cpp/m78xylop9wA 2/7
3/20/22, 6:28 PM - Examples - Generic Programming Templates in C++
72     writeMessagePointer(messPoin2);
73     writeMessagePointer(messPoin3);
74   
75     std::cout << std::endl;
76
77 }
78

Output 1.65s

3.683e-05 sec. elapsed: information

7.225e-05 sec. elapsed: warning

7.8333e-05 sec. elapsed: unexpected

8.6616e-05 sec. elapsed: information

9.2283e-05 sec. elapsed: warning

9.8207e-05 sec. elapsed: unexpected

Note: std::cerr of the class std::ostream represents the standard error


stream. This is not a runtime error.

Explanation#
The structs in lines 15, 21, and 27 know, what they should display if used.
The key idea is that the static type MessageSeverity differs from the dynamic
type such as MessageInformation (line 61); therefore, the late binding will kick
in and the writeMessage methods in lines 71, 72, and 73 are of the dynamic
types. Dynamic polymorphism requires a kind of indirection. We can use
https://www.educative.io/courses/generic-templates-in-cpp/m78xylop9wA 3/7
3/20/22, 6:28 PM - Examples - Generic Programming Templates in C++
yp y p y p q
references (57-59) or pointers (67-69).

From a performance perspective, we can do better and make the dispatch at


compile time.

Example 2: Dispatch with Static


Polymorphism#
1 // DispatchStaticPolymorphism.cpp
2
3 #include <chrono>
4 #include <iostream>
5
6 auto start = std::chrono::steady_clock::now();
7
8 void writeElapsedTime(){
9     auto now = std::chrono::steady_clock::now();
10     std::chrono::duration<double> diff = now - start;
11   
12     std::cerr << diff.count() << " sec. elapsed: ";
13 }
14
15 template <typename ConcreteMessage>                        
16 struct MessageSeverity{
17   void writeMessage(){                                    
18     static_cast<ConcreteMessage*>(this)->writeMessageImplementation();
19   }
20   void writeMessageImplementation() const {
21     std::cerr << "unexpected" << std::endl;
22   }
23 };
24
25 struct MessageInformation: MessageSeverity<MessageInformation>{
26   void writeMessageImplementation() const {              
27     std::cerr << "information" << std::endl;
28   }
29 };
30
31 struct MessageWarning: 
32 MessageSeverity<MessageWarning>{
33   void writeMessageImplementation() const {               
34     std::cerr << "warning" << std::endl;
35   }
36 };
https://www.educative.io/courses/generic-templates-in-cpp/m78xylop9wA 4/7
3/20/22, 6:28 PM - Examples - Generic Programming Templates in C++
37
38 struct MessageFatal: 
39 MessageSeverity<MessageFatal>{};     
40
41 template <typename T>
42 void writeMessage(T& messServer){                       
43   
44   writeElapsedTime();                                   
45   messServer.writeMessage();                            
46   
47 }
48
49 int main(){
50
51     std::cout << std::endl;
52   
53     MessageInformation messInfo;
54     writeMessage(messInfo);
55     
56     MessageWarning messWarn;
57     writeMessage(messWarn);
58   
59     MessageFatal messFatal;
60     writeMessage(messFatal);
61   
62     std::cout << std::endl;
63
64 }
65

(/learn)
Output 1.28s

4.0768e-05 sec. elapsed: information

7.5223e-05 sec. elapsed: warning

8.138e-05 sec. elapsed: unexpected

https://www.educative.io/courses/generic-templates-in-cpp/m78xylop9wA 5/7
3/20/22, 6:28 PM - Examples - Generic Programming Templates in C++

Note: std::cerr of the class std::ostream represents the standard error


stream. This is not a runtime error.

Explanation#
In this case, all concrete structs in lines 25, 31, and 38 are derived from the
base class MessageSeverity . The method writeMessage serves as an interface
that dispatches to the concrete implementations
writeMessageImplementation . To make that happen, the object will be
upcasted to the ConcreteMessage :

static_cast<ConcreteMessage*>(this)->writeMessageImplementation();

This is the dispatch at compile time; therefore, this technique is called static
polymorphism.

To be honest, it took me a bit of time to get used to it but applying static


polymorphism like that on line 42 is actually quite easy.

We’ll solve an exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

https://www.educative.io/courses/generic-templates-in-cpp/m78xylop9wA 6/7
3/20/22, 6:28 PM - Examples - Generic Programming Templates in C++

Back Next

Static Versus Dynamic Polymorphism - Exercise

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/m78xylop9wA 7/7
3/20/22, 6:28 PM - Exercise - Generic Programming Templates in C++

- Exercise
Let's solve an exercise in this lesson.

We'll cover the following

• Problem Statement

Problem Statement#
Polymorphism can be simulated in various ways. Implement the
polymorphism with if , with switch , and with a dispatch table
(https://en.wikipedia.org/wiki/Dispatch_table) and compare the three
implementations using static and dynamic polymorphism.

1 #include <iostream>
2
3 // Write your code here
(/learn)
4 // After writing your code uncomment the lines in main
5
6 int main() {
7   
8   std::cout << std::endl;
9 /*  
10   writeMessage(MessageSeverity::information);
11   writeMessage(MessageSeverity::warning);
12   writeMessage(MessageSeverity::fatal);
13 */
14   std::cout << std::endl;
15   
16 }

https://www.educative.io/courses/generic-templates-in-cpp/qV4lXrrgQVy 1/2
3/20/22, 6:28 PM - Exercise - Generic Programming Templates in C++

Let’s look at different solutions for this exercise in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Examples - Solution

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qV4lXrrgQVy 2/2
3/20/22, 6:29 PM - Solution - Generic Programming Templates in C++

- Solution
In this lesson, we'll look at different solution reivews for the last exercise.

We'll cover the following

• Solution 1: Using the if Statement

• Explanation
• Solution 2: Using the switch statement

• Explanation
• Solution 3: Using a Dispatch Table

• Explanation

Solution 1: Using the if Statement#


1 // dispatchIf.cpp
2
3 #include <chrono>
4 #include <iostream>
5
6 enum class MessageSeverity{                                 
7     information,
8     warning,
9     fatal,
10 };
11
12 auto start = std::chrono::steady_clock::now();              
13
14 void writeElapsedTime(){                                   
15     auto now = std::chrono::steady_clock::now();            
16     std::chrono::duration<double> diff = now - start;
17   
18     std::cerr << diff.count() << " sec. elapsed: ";
19 }
https://www.educative.io/courses/generic-templates-in-cpp/qV2qOOk2D5G 1/8
3/20/22, 6:29 PM - Solution - Generic Programming Templates in C++
19 }
20
21 void writeInformation(){ std::cerr << "information" << std::endl; }
22 void writeWarning(){ std::cerr << "warning" << std::endl; }
23 void writeUnexpected(){ std::cerr << "unexpected" << std::endl; }
24
25 void writeMessage(MessageSeverity messServer){               
26     
27     writeElapsedTime();                                      
28     
29     if (MessageSeverity::information == messServer){
30         writeInformation();
31     }
32     else if (MessageSeverity::warning == messServer){
33         writeWarning();
34     }
35     else{
36         writeUnexpected();
37     }
38   
39 }
40
41 int main(){
42
43     std::cout << std::endl;
44   
45     writeMessage(MessageSeverity::information);
46     writeMessage(MessageSeverity::warning);
47     writeMessage(MessageSeverity::fatal);
48
49     std::cout << std::endl;
50
51 }
52

Output 2.51s

4.2308e-05 sec. elapsed: information

8.3169e-05 sec. elapsed: warning

8.947e-05 sec. elapsed: unexpected

https://www.educative.io/courses/generic-templates-in-cpp/qV2qOOk2D5G 2/8
3/20/22, 6:29 PM - Solution - Generic Programming Templates in C++

Explanation#

Note: std::cerr of the class std::ostream represents the standard


error stream. This is not a runtime error.

The function writeMessage in line 25 displays the elapsed time in seconds in


line 27 since the start of the program and a log message. It uses an
enumeration in line 6 for the message severity. We used the start time in line
12 and the current time in line 15 to calculate the elapsed time. As the name
suggests, the std::steady_clock cannot be adjusted; therefore, it is the right
choice for this measurement. The key part of the program is the part of the
function writeMessage in line 25, in which we made the decision which
message should be displayed. In this case, we used if-else statements.

Solution 2: Using the switch


statement#
1 // dispatchSwitch
2
3 #include <chrono>
4 #include <iostream>
5
6 enum class MessageSeverity{
7     information,
8     warning,
9     fatal,
10 };
11
12 auto start = std::chrono::steady_clock::now();
13
14 void writeElapsedTime(){
15     auto now = std::chrono::steady_clock::now();
16     std::chrono::duration<double> diff = now - start;
17
https://www.educative.io/courses/generic-templates-in-cpp/qV2qOOk2D5G 3/8
3/20/22, 6:29 PM - Solution - Generic Programming Templates in C++
17   
18     std::cerr << diff.count() << " sec. elapsed: ";
19 }
20
21 void writeInformation(){ std::cerr << "information" << std::endl; }
22 void writeWarning(){ std::cerr << "warning" << std::endl; }
23 void writeUnexpected(){ std::cerr << "unexpected" << std::endl; }
24
25 void writeMessage(MessageSeverity messSever){
26     
27     writeElapsedTime();
28
29     switch(messSever){
30         case MessageSeverity::information:
31             writeInformation();
32             break;
33         case MessageSeverity::warning:
34             writeWarning();
35             break;
36         default:
37             writeUnexpected();
38             break;
39   }
40   
41 }
42
43 int main(){
44
45     std::cout << std::endl;
46   
47     writeMessage(MessageSeverity::information);
48     writeMessage(MessageSeverity::warning);
49     writeMessage(MessageSeverity::fatal);
50
51     std::cout << std::endl;
52
53 }
54

Output 1.67s

3 7315e 05 sec elapsed: information


https://www.educative.io/courses/generic-templates-in-cpp/qV2qOOk2D5G 4/8
3/20/22, 6:29 PM - Solution - Generic Programming Templates in C++
3.7315e-05 sec. elapsed: information

7.1661e-05 sec. elapsed: warning

7.8107e-05 sec. elapsed: unexpected

Explanation#

Note: std::cerr of the class std::ostream represents the standard


error stream. This is not a runtime error.

The following program is quite similar to the previous one. Only the
implementation of the function writeMessage changed. The function
writeMessage in line 25 displays the elapsed time in seconds (line 27) since
the start of the program and a log message. It uses an enumeration (line 6)
for the message severity. We used the start time (line 12) and the current
time (line 15) to calculate the elapsed time. As the name suggested, the
std::steady_clock cannot be adjusted; therefore, it is the right choice for
this measurement. The key part of the program is the part of the function
writeMessage (line 25), in which we made the decision which message
should be displayed. In this case, we used the switch statements.

To be honest, I had to look up the syntax for the switch statements to make
it right.

Solution 3: Using a Dispatch Table#


1 // dispatchHasttables
2
3 #include <chrono>
4 #include <functional>
5 #include <iostream>
6 #include <unordered_map>
7
8 enum class MessageSeverity{
https://www.educative.io/courses/generic-templates-in-cpp/qV2qOOk2D5G 5/8
3/20/22, 6:29 PM - Solution - Generic Programming Templates in C++

9   information,
10   warning,
11   fatal,
12 };
13
14 auto start = std::chrono::steady_clock::now();
15
16 void writeElapsedTime(){
17     auto now = std::chrono::steady_clock::now();
18     std::chrono::duration<double> diff = now - start;
19   
20     std::cerr << diff.count() << " sec. elapsed: ";
21 }
22
23 void writeInformation(){ std::cerr << "information" << std::endl; }
24 void writeWarning(){ std::cerr << "warning" << std::endl; }
25 void writeUnexpected(){ std::cerr << "unexpected" << std::endl; }
26
27 std::unordered_map<MessageSeverity, std::function<void()>> mess2Func{
28     {MessageSeverity::information, writeInformation},
29     {MessageSeverity::warning, writeWarning},
30     {MessageSeverity::fatal, writeUnexpected}
31 };
32
33 void writeMessage(MessageSeverity messServer){
34   
35   writeElapsedTime();
36   
37   mess2Func[messServer]();
38   
39 }
40
41 int main(){
42
43   std::cout << std::endl;
44   
45   writeMessage(MessageSeverity::information);
46   writeMessage(MessageSeverity::warning);
47   writeMessage(MessageSeverity::fatal);
48
49   std::cout << std::endl;
50
51 }
52

https://www.educative.io/courses/generic-templates-in-cpp/qV2qOOk2D5G 6/8
3/20/22, 6:29 PM - Solution - Generic Programming Templates in C++

Output 1.95s

(/learn)

4.3472e-05 sec. elapsed: information

8.3768e-05 sec. elapsed: warning

9.0492e-05 sec. elapsed: unexpected

Explanation#

Note: std::cerr of the class std::ostream represents the standard


error stream. This is not a runtime error.

With the if-else or the switch statement, we used enumerator for


dispatching to the right case. The key to our dispatch table behaves in a
similar way.

Dynamic or static polymorphism is totally different. Instead of an


enumerator or a key for dispatching to the right action, we used objects
which decide autonomously at runtime (dynamic polymorphism) or
compile-time (static polymorphism) what should be done.

Let’s move on to CRTP in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022
https://www.educative.io/courses/generic-templates-in-cpp/qV2qOOk2D5G 7/8
3/20/22, 6:29 PM - Solution - Generic Programming Templates in C++

Back Next

- Exercise CRTP

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qV2qOOk2D5G 8/8
3/20/22, 6:30 PM CRTP - Generic Programming Templates in C++

CRTP
Let's learn about CRTP in this lesson.

We'll cover the following

• CRTP

• Typical use-case
• Mixins

• Static Polymorphism

CRTP#
The acronym CRTP
(https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) stands
for the C++ idiom Curiously Recurring Template Pattern and is a technique
in C++ in which a Derived class derives from a class template Base . The key
is that Base has Derived as a template argument.

Let’s have a look at an example:

template<class T> 

class Base{

   ...

};

class Derived: public Base<Derived>{ 

   ...

};

https://www.educative.io/courses/generic-templates-in-cpp/gkY9jRmxOm6 1/4
3/20/22, 6:30 PM CRTP - Generic Programming Templates in C++

CRTP enables static polymorphism.

Typical use-case#
There are two typical use-cases for CRTP: Mixins and static polymorphism.

Mixins#
Mixins (https://en.wikipedia.org/wiki/Mixin) is a popular concept in the
design of classes to mix in new code. Therefore, it’s an often-used technique
in Python to change the behavior of a class by using multiple inheritances.
In contrast to C++, in Python, it is legal to have more than one definition of a
method in a class hierarchy. Python simply uses the method that is first in
the Method Resolution Order (https://docs.python.org/3/glossary.html#term-
method-resolution-order) (MRO).

You can implement mixins in C++ by using CRTP. A prominent example is the
class std::enable_shared_from_this . By using this class, you can create
objects that return an std::shared_ptr to themselves. We have to derive
your class MySharedClass public from std::enable_shared_from_this . Now,
our class MySharedClass has a method shared_from_this .

An additional
(/learn) typical use-case for mixins is a class that you want to extend
with the capability that their instances support the comparison for equality
and inequality.

Static Polymorphism#
Static polymorphism is quite similar to dynamic polymorphism. But
contrary to dynamic polymorphism with virtual methods, the dispatch of the
https://www.educative.io/courses/generic-templates-in-cpp/gkY9jRmxOm6 f 2/4
3/20/22, 6:30 PM CRTP - Generic Programming Templates in C++

method calls will take place at compile-time. Now, we are at the center of the
CRTP idiom.

class ShareMe: public std::enable_shared_from_this<ShareMe>{

  std::shared_ptr<ShareMe> getShared(){

    return shared_from_this();

  } 

};

std::enable_shared_from_this creates a shared _ptr for an object.

std::enable_shared_from_this: base class of the object.

shared_from_this: returns the shared object

To learn more about CRTP, click here


(https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).

In the next lesson, we’ll look at a couple of examples of CRTP.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solution - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/gkY9jRmxOm6 3/4
3/20/22, 6:30 PM CRTP - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/gkY9jRmxOm6 4/4
3/20/22, 6:32 PM - Examples - Generic Programming Templates in C++

- Examples
In this lesson, we'll see a couple of examples of CRTP.

We'll cover the following

• Example 1: Mixins with CRTP

• Explanation
• Example 2: Static Polymorphism with CRTP

• Explanation

Example 1: Mixins with CRTP#


1 // templateCRTPRelational.cpp
2
3 #include <iostream>
4 #include <string>
5
6 template<class Derived>
7 class Relational{};
8
9 // Relational Operators
10
11 template <class Derived>
12 bool operator > (Relational<Derived> const& op1, Relational<Derived> const & op2){
13     Derived const& d1 = static_cast<Derived const&>(op1);     
14     Derived const& d2 = static_cast<Derived const&>(op2); 
15     return d2 < d1;
16 }
17
18 template <class Derived>
19 bool operator == (Relational<Derived> const& op1, Relational<Derived> const & op2){
20     Derived const& d1 = static_cast<Derived const&>(op1);     
21     Derived const& d2 = static_cast<Derived const&>(op2); 
22     return !(d1 < d2) && !(d2 < d1);
23 }
https://www.educative.io/courses/generic-templates-in-cpp/BnGoJ6LLAVn 1/7
3/20/22, 6:32 PM - Examples - Generic Programming Templates in C++
23 }
24
25 template <class Derived>
26 bool operator != (Relational<Derived> const& op1, Relational<Derived> const & op2){
27     Derived const& d1 = static_cast<Derived const&>(op1);     
28     Derived const& d2 = static_cast<Derived const&>(op2); 
29     return (d1 < d2) || (d2 < d1);
30 }
31
32 template <class Derived>
33 bool operator <= (Relational<Derived> const& op1, Relational<Derived> const & op2){
34     Derived const& d1 = static_cast<Derived const&>(op1);     
35     Derived const& d2 = static_cast<Derived const&>(op2); 
36     return (d1 < d2) || (d1 == d2);
37 }
38
39 template <class Derived>
40 bool operator >= (Relational<Derived> const& op1, Relational<Derived> const & op2){
41     Derived const& d1 = static_cast<Derived const&>(op1);     
42     Derived const& d2 = static_cast<Derived const&>(op2); 
43     return (d1 > d2) || (d1 == d2);
44 }
45
46 // Apple
47
48 class Apple:public Relational<Apple>{
49 public:
50     explicit Apple(int s): size{s}{};
51     friend bool operator < (Apple const& a1, Apple const& a2){
52         return a1.size < a2.size;
53     }
54 private:
55     int size;
56 };
57
58 // Man
59
60 class Man:public Relational<Man>{
61 public:
62     explicit Man(const std::string& n): name{n}{}
63     friend bool operator < (Man const& m1, Man const& m2){
64         return m1.name < m2.name;
65     }
66 private:
67     std::string name;
68 };
69
70 int main(){
71   
72   std::cout << std::boolalpha << std::endl;
73   
74   Apple apple1{5};
https://www.educative.io/courses/generic-templates-in-cpp/BnGoJ6LLAVn 2/7
3/20/22, 6:32 PM - Examples - Generic Programming Templates in C++

75   Apple apple2{10}; 
76   std::cout << "apple1 < apple2: " << (apple1 < apple2) << std::endl;
77   std::cout << "apple1 > apple2: " << (apple1 > apple2) << std::endl;
78   std::cout << "apple1 == apple2: " << (apple1 == apple2) << std::endl;
79   std::cout << "apple1 != apple2: " << (apple1 != apple2) << std::endl;
80   std::cout << "apple1 <= apple2: " << (apple1 <= apple2) << std::endl;
81   std::cout << "apple1 >= apple2: " << (apple1 >= apple2) << std::endl;
82   
83   std::cout << std::endl;
84     
85   Man man1{"grimm"};
86   Man man2{"jaud"};
87   std::cout << "man1 < man2: " << (man1 < man2) << std::endl; 
88   std::cout << "man1 > man2: " << (man1 > man2) << std::endl; 
89   std::cout << "man1 == man2: " << (man1 == man2) << std::endl; 
90   std::cout << "man1 != man2: " << (man1 != man2) << std::endl;
91   std::cout << "man1 <= man2: " << (man1 <= man2) << std::endl;
92   std::cout << "man1 >= man2: " << (man1 >= man2) << std::endl;
93   
94   std::cout << std::endl;
95     
96 }
97

Output 1.35s

apple1 < apple2: true

apple1 > apple2: false

apple1 == apple2: false

apple1 != apple2: true

apple1 <= apple2: true

apple1 >= apple2: false

man1 < man2: true

Explanation#
https://www.educative.io/courses/generic-templates-in-cpp/BnGoJ6LLAVn 3/7
3/20/22, 6:32 PM - Examples - Generic Programming Templates in C++

We have implemented, for the classes Apple and Man , the smaller operator
separately (lines 51-52 and 63-64). The classes Man and Apple are publicly
derived (line 48 and 60) from the class Relational<Man> and
Ralational<Apple> . We have implemented for classes of the kind Relational
the greater than operator > (lines 11 – 16), the equality operator == (lines 18
– 23), the not equal operator != (lines 25 – 30), the less than or equal
operator <= (line 32 – 37) and the greater than or equal operator >= (lines
39 – 44). The less than or equal ( <= ) and greater than or equal ( >= )
operators used the equality operator == (line 36 and 43). All these operators
convert their operands: Derived const&: Derived const& d1 =
static_cast<Derived const&>(op1) .

In the main program, we have compared Apple and Man classes for all the
above-mentioned operators.

Example 2: Static Polymorphism with


CRTP#
1 // templateCRTP.cpp
2
3 #include <iostream>
4
5 template <typename Derived>
6 struct Base{
7   void interface(){
8     static_cast<Derived*>(this)->implementation();
9   }
10   
11   void implementation(){
12     std::cout << "Implementation Base" << std::endl;
13   }
14 };
15
16 struct Derived1: Base<Derived1>{
17   void implementation(){
18 std::cout << "Implementation Derived1" << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/BnGoJ6LLAVn 4/7
3/20/22, 6:32 PM - Examples - Generic Programming Templates in C++
18     std::cout <<  Implementation Derived1  << std::endl;
19   }
20 };
21
22 struct Derived2: Base<Derived2>{
23   void implementation(){
24     std::cout << "Implementation Derived2" << std::endl;
25   }
26 };
27
28 struct Derived3: Base<Derived3>{};
29
30 template <typename T>
31 void execute(T& base){
32   base.interface();
33 }
34
35 int main(){
36   
37   std::cout << std::endl;
38   
39   Derived1 d1;
40   execute(d1);
41     
42   Derived2 d2;
43   execute(d2);
44   
45   Derived3 d3;
46   execute(d3);
47   
48   std::cout << std::endl;
49   
50 }
51

(/learn)

Output 1.29s

Implementation Derived1

Implementation Derived2

Implementation Base

https://www.educative.io/courses/generic-templates-in-cpp/BnGoJ6LLAVn 5/7
3/20/22, 6:32 PM - Examples - Generic Programming Templates in C++

Explanation#
We have used static polymorphism in the function template execute (lines
30-33). We invoked the method base.interface on each base argument. The
method Base::interface , in lines (7-9), is the key point of the CRTP idiom.
The methods dispatch to the implementation of the derived class:
static_cast<Derived*>(this)->implementation() . That is possible because the
method will be instantiated when called. At this point in time, the derived
classes Derived1 , Derived2 , and Derived3 are fully defined. Therefore, the
method Base::interface can use the details of its derived classes. Especially
interesting is the method Base::implementation (lines 11-13). This method
plays the role of a default implementation for the static polymorphism for
the class Derived3 (line 28).

We’ll solve a few exercises around CRTP in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

CRTP - Exercises

Mark as Completed

https://www.educative.io/courses/generic-templates-in-cpp/BnGoJ6LLAVn 6/7
3/20/22, 6:32 PM - Examples - Generic Programming Templates in C++

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/BnGoJ6LLAVn 7/7
3/20/22, 6:33 PM - Exercises - Generic Programming Templates in C++

- Exercises
Let's solve a few exercises around CRTP in this lesson.

We'll cover the following

• Problem Statement 1

• Problem Statement 2
• Problem Statement 3

• Case 1:
• Case 2:

• Case 3:

• Problem Statement 4

Problem Statement 1#
Extend the given piece of code with a
Person class. A Person should have a

first name
last name

You need to create two objects of the Person class and compare these objects
using relational operators.

1 #include <iostream>
2 #include <string>
3
4 template<class Derived>
5 class Relational{};
https://www.educative.io/courses/generic-templates-in-cpp/qA6KLqVWWJy 1/8
3/20/22, 6:33 PM - Exercises - Generic Programming Templates in C++
6
7 // Relational Operators
8
9 template <class Derived>
10 bool operator > (Relational<Derived> const& op1, Relational<Derived> const & op2){
11     Derived const& d1 = static_cast<Derived const&>(op1);     
12     Derived const& d2 = static_cast<Derived const&>(op2); 
13     return d2 < d1;
14 }
15
16 template <class Derived>
17 bool operator == (Relational<Derived> const& op1, Relational<Derived> const & op2){
18     Derived const& d1 = static_cast<Derived const&>(op1);     
19     Derived const& d2 = static_cast<Derived const&>(op2); 
20     return !(d1 < d2) && !(d2 < d1);
21 }
22
23 template <class Derived>
24 bool operator != (Relational<Derived> const& op1, Relational<Derived> const & op2){
25     Derived const& d1 = static_cast<Derived const&>(op1);     
26     Derived const& d2 = static_cast<Derived const&>(op2); 
27     return (d1 < d2) || (d2 < d1);
28 }
29
30 template <class Derived>
31 bool operator <= (Relational<Derived> const& op1, Relational<Derived> const & op2){
32     Derived const& d1 = static_cast<Derived const&>(op1);     
33     Derived const& d2 = static_cast<Derived const&>(op2); 
34     return (d1 < d2) || (d1 == d2);
35 }
36
37 template <class Derived>
38 bool operator >= (Relational<Derived> const& op1, Relational<Derived> const & op2){
39     Derived const& d1 = static_cast<Derived const&>(op1);     
40     Derived const& d2 = static_cast<Derived const&>(op2); 
41     return (d1 > d2) || (d1 == d2);
42 }
43
44 // Implement a person class here
45
46 // Person
47
48 // Apple
49
50 class Apple:public Relational<Apple>{
51 public:
52     explicit Apple(int s): size{s}{};
53     friend bool operator < (Apple const& a1, Apple const& a2){
54         return a1.size < a2.size;
55     }
56 private:
57     int size;
https://www.educative.io/courses/generic-templates-in-cpp/qA6KLqVWWJy 2/8
3/20/22, 6:33 PM - Exercises - Generic Programming Templates in C++
57     int size;
58 };
59
60 // Man
61
62 class Man:public Relational<Man>{
63 public:
64     explicit Man(const std::string& n): name{n}{}
65     friend bool operator < (Man const& m1, Man const& m2){
66         return m1.name < m2.name;
67     }
68 private:
69     std::string name;
70 };
71
72 int main(){
73   
74   std::cout << std::boolalpha << std::endl;
75   
76   // Call Person class object here checks them for all relational operaotrs
77   
78   std::cout << std::endl;
79     
80 }
81

Output 2.63s

Problem Statement 2#
In example 2
(https://www.educative.io/collection/page/10370001/5799373671759872/5296
384649461760#example-1-static-polymorphism-with-crtp), how can you
prevent a derived class which has the wrong template parameter: Derived4:
https://www.educative.io/courses/generic-templates-in-cpp/qA6KLqVWWJy 3/8
p
3/20/22, 6:33 PM
g p p
- Exercises - Generic Programming Templates in C++

Base<Derived3>

1 // templateCRTP.cpp
2
3 #include <iostream>
4
5 template <typename Derived>
6 struct Base{
7   void interface(){
8     static_cast<Derived*>(this)->implementation();
9   }
10   void implementation(){
11     std::cout << "Implementation Base" << std::endl;
12   }
13 };
14
15 struct Derived1: Base<Derived1>{
16   void implementation(){
17     std::cout << "Implementation Derived1" << std::endl;
18   }
19 };
20
21 struct Derived2: Base<Derived2>{
22   void implementation(){
23     std::cout << "Implementation Derived2" << std::endl;
24   }
25 };
26
27 struct Derived3: Base<Derived3>{};
28
29 template <typename T>
30 void execute(T& base){
31     base.interface();
32 }
33
34 // Write the struct here
35
36 int main(){
37   
38   std::cout << std::endl;
39   
40   // call the function here
41   
42   std::cout << std::endl;
43   
44 }
45

https://www.educative.io/courses/generic-templates-in-cpp/qA6KLqVWWJy 4/8
3/20/22, 6:33 PM - Exercises - Generic Programming Templates in C++

Output 2.39s

Problem Statement 3#
The functionality of the program in example 1
(https://www.educative.io/collection/page/10370001/5799373671759872/5296
384649461760#example-1-static-polymorphism-with-crtp) of the previous
lesson can be implemented in various ways. Implement each variant.

Case 1:#
Object-oriented with dynamic polymorphism.

1 #include <iostream>
2
3 // Implement the functionality here
4
5 int main() {
6   // call the function here
7   return 0;
8 }

Case 2:#
Just a function template.
https://www.educative.io/courses/generic-templates-in-cpp/qA6KLqVWWJy 5/8
3/20/22, 6:33 PM - Exercises - Generic Programming Templates in C++

1 #include <iostream>
2
3 // write your function template here
4
5 int main() {
6   // Call the function here
7 }

Case 3:#
To solve this exercise with Concepts
(https://www.educative.io/collection/page/10370001/5799373671759872/5589
499255980032), you have to peek into the last chapter of this course. Solving
this exercise with Concepts
(https://www.educative.io/collection/page/10370001/5799373671759872/5589
499255980032) is also a valid and elegant way.

Concepts with C++20:

1 #include <iostream>
2
3 // Implement it using C++20 concept
4
5 int main() {
6   // your code goes here
7 }

Problem Statement 4#
Implement the class ShareMe and use it.
https://www.educative.io/courses/generic-templates-in-cpp/qA6KLqVWWJy 6/8
3/20/22, 6:33 PM - Exercises - Generic Programming Templates in C++

(/learn)
Objects of the class ShareMe should return an std::shared_ptr to
themselves.

1 #include <iostream>
2
3 // Implement the class here
4
5 int main() {
6   // After implementing the shareMe class uncomment the code given below
7
8   /*
9   std::cout << std::endl;
10
11   // share the same ShareMe object
12   std::shared_ptr<ShareMe> shareMe(new ShareMe);
13   std::shared_ptr<ShareMe> shareMe1= shareMe->getShared();
14
15   // both resources have the same address
16   std::cout << "Address of resource of shareMe "<< (void*)shareMe.get() << " " << st
17   std::cout << "Address of resource of shareMe1 "<< (void*)shareMe1.get() << " " << 
18
19   // the use_count is 2
20   std::cout << "shareMe.use_count(): "<< shareMe.use_count() << std::endl;
21   std::cout << std::endl;
22   */
23 }

In the next lesson, we’ll look at solutions to these exercises.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join hired com/educative/?
https://www.educative.io/courses/generic-templates-in-cpp/qA6KLqVWWJy 7/8
3/20/22, 6:33 PM - Exercises - Generic Programming Templates in C++
(https://join.hired.com/educative/?

utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Examples - Solutions

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qA6KLqVWWJy 8/8
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++

- Solutions
Let's look at the solutions of the exercises, we had in the last lesson.

We'll cover the following

• Solution of Problem Statement 1

• Explanation
• Solution of Problem Statement 2

• Explanation
• Solution to Problem Statement 3 (Case 1)

• Explanation

• Solution to Problem Statement 3 (Case 2)


• Explanation
• Solution to Problem Statement 3 (Case 3)
• Explanation

• Solution to Problem Statement 4


• Explanation

Solution of Problem Statement 1#


1 // templateCRTPRelational.cpp
2
3 #include <iostream>
4 #include <string>
5 #include <utility>
6
7 template<class Derived>
8 class Relational{};
https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 1/14
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++
8 class Relational{};
9
10 // Relational Operators
11
12 template <class Derived>
13 bool operator > (Relational<Derived> const& op1, Relational<Derived> const & op2){
14     Derived const& d1 = static_cast<Derived const&>(op1);     
15     Derived const& d2 = static_cast<Derived const&>(op2); 
16     return d2 < d1;
17 }
18
19 template <class Derived>
20 bool operator == (Relational<Derived> const& op1, Relational<Derived> const & op2){
21     Derived const& d1 = static_cast<Derived const&>(op1);     
22     Derived const& d2 = static_cast<Derived const&>(op2); 
23     return !(d1 < d2) && !(d2 < d1);
24 }
25
26 template <class Derived>
27 bool operator != (Relational<Derived> const& op1, Relational<Derived> const & op2){
28     Derived const& d1 = static_cast<Derived const&>(op1);     
29     Derived const& d2 = static_cast<Derived const&>(op2); 
30     return (d1 < d2) || (d2 < d1);
31 }
32
33 template <class Derived>
34 bool operator <= (Relational<Derived> const& op1, Relational<Derived> const & op2){
35     Derived const& d1 = static_cast<Derived const&>(op1);     
36     Derived const& d2 = static_cast<Derived const&>(op2); 
37     return (d1 < d2) || (d1 == d2);
38 }
39
40 template <class Derived>
41 bool operator >= (Relational<Derived> const& op1, Relational<Derived> const & op2){
42     Derived const& d1 = static_cast<Derived const&>(op1);     
43     Derived const& d2 = static_cast<Derived const&>(op2); 
44     return (d1 > d2) || (d1 == d2);
45 }
46
47 // Apple
48
49 class Apple: public Relational<Apple>{
50 public:
51     explicit Apple(int s): size{s}{};
52     friend bool operator < (Apple const& a1, Apple const& a2){
53         return a1.size < a2.size;
54     }
55 private:
56     int size;
57 };
58
59 // Man
https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 2/14
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++

60
61 class Man: public Relational<Man>{
62 public:
63     explicit Man(const std::string& n): name{n}{}
64     friend bool operator < (Man const& m1, Man const& m2){
65         return m1.name < m2.name;
66     }
67 private:
68     std::string name;
69 };
70
71 // class Person
72 class Person: public Relational<Person>{
73 public:
74     Person(std::string fst, std::string sec): first(fst), last(sec){}
75     friend bool operator < (Person const& p1, Person const& p2){
76         return std::make_pair(p1.first, p1.last) < std::make_pair(p2.first, p2.last)
77     }
78 private:
79     std::string first;
80     std::string last;
81 };
82         
83
84 int main(){
85   
86   std::cout << std::boolalpha << std::endl;
87   
88   Apple apple1{5};
89   Apple apple2{10}; 
90   std::cout << "apple1 < apple2: " << (apple1 < apple2) << std::endl;
91   std::cout << "apple1 > apple2: " << (apple1 > apple2) << std::endl;
92   std::cout << "apple1 == apple2: " << (apple1 == apple2) << std::endl;
93   std::cout << "apple1 != apple2: " << (apple1 != apple2) << std::endl;
94   std::cout << "apple1 <= apple2: " << (apple1 <= apple2) << std::endl;
95   std::cout << "apple1 >= apple2: " << (apple1 >= apple2) << std::endl;
96   
97   std::cout << std::endl;
98     
99   Man man1{"grimm"};
100   Man man2{"jaud"};
101   std::cout << "man1 < man2: " << (man1 < man2) << std::endl; 
102   std::cout << "man1 > man2: " << (man1 > man2) << std::endl; 
103   std::cout << "man1 == man2: " << (man1 == man2) << std::endl; 
104   std::cout << "man1 != man2: " << (man1 != man2) << std::endl;
105   std::cout << "man1 <= man2: " << (man1 <= man2) << std::endl;
106   std::cout << "man1 >= man2: " << (man1 >= man2) << std::endl;
107   
108   std::cout << std::endl;
109   
110   Person rainer{"Rainer", "Grimm"};
111 Person marius{"Marius" "Grimm"};
https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 3/14
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++
111   Person marius{ Marius ,  Grimm };
112   std::cout << "rainer < marius: " << (rainer < marius) << std::endl; 
113   std::cout << "rainer > marius: " << (rainer > marius) << std::endl; 
114   std::cout << "rainer == marius: " << (rainer == marius) << std::endl; 
115   std::cout << "rainer != marius: " << (rainer != marius) << std::endl;
116   std::cout << "rainer <= marius: " << (rainer <= marius) << std::endl;
117   std::cout << "rainer >= marius: " << (rainer >= marius) << std::endl;
118   
119   std::cout << std::endl;  
120 }

Output 1.61s

apple1 < apple2: true

apple1 > apple2: false

apple1 == apple2: false

apple1 != apple2: true

apple1 <= apple2: true

apple1 >= apple2: false

man1 < man2: true

Explanation#
In the above code, we have defined the Person class which contains the
string variables, i.e., first and last and a < operator to compare two
people’s lengths in lines 75 – 77. The class Person is publicly derived (line 72)
from the class Relational<Person> . We have implemented for classes of the
kind Relational the greater than operator > (lines 12 - 17), the equality
operator == (lines 19 - 24), the not equal operator != (lines 26 - 31), the less
than or equal operator <= (line 33 - 38) and the greater than or equal
operator >= (lines 40 - 45). The less than or equal and greater than or equal
operators used the equality operator (line 37 and 44). All these operators
convert their operands: Derived const&: Derived const& d1 =
https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 4/14
3/20/22, 6:36 PM
p - Solutions - Generic Programming Templates in C++

static_cast<Derived const&>(op1) .

In the main program, we have compared Apple , Man , and Person classes for
all the above-mentioned operators.

Solution of Problem Statement 2#


1 // templateCRTPCheck.cpp
2
3 #include <iostream>
4
5 template <typename Derived>
6 struct Base{
7   void interface(){
8     static_cast<Derived*>(this)->implementation();
9   }
10   void implementation(){
11     std::cout << "Implementation Base" << std::endl;
12   }
13 private:
14     Base(){};
15     friend Derived;
16 };
17
18 struct Derived1: Base<Derived1>{
19   void implementation(){
20     std::cout << "Implementation Derived1" << std::endl;
21   }
22 };
23
24 struct Derived2: Base<Derived2>{
25   void implementation(){
26     std::cout << "Implementation Derived2" << std::endl;
27   }
28 };
29
30 struct Derived3: Base<Derived3>{};
31
32 // struct Derived4: Base<Derived3>{};
33
34 template <typename T>
35 void execute(T& base){
36     base.interface();
37 }
38
39 int main(){
https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 5/14
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++

40   
41   std::cout << std::endl;
42   
43   Derived1 d1;
44   execute(d1);
45     
46   Derived2 d2;
47   execute(d2);
48   
49   Derived3 d3;
50   execute(d3);
51   
52   // Derived4 d4;
53   
54   std::cout << std::endl;
55   
56 }

Output 2.02s

Implementation Derived1

Implementation Derived2

Implementation Base

Explanation#
We have used static polymorphism in the function template execute (lines
34 – 37). We invoked the method base.interface on each base argument.
The method Base::interface , in lines (7 – 9), is the key point of the CRTP
idiom. The method dispatches to the implementation of the derived class:
static_cast<Derived*>(this)->implementation() . That is possible because the
method will be instantiated when called. At this point in time, the derived
classes Derived1 , Derived2 , and Derived3 are fully defined. Therefore, the
https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 6/14
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++

method Base::interface can use the details of its derived classes. Especially

interesting is the method Base::implementation (lines 10 – 12). This method


plays the role of a default implementation for the static polymorphism for
the class Derived3 (line 30).

The constructor of the derived class has to call the constructor of the base
class. The constructor in the base class is private. Only type T can invoke the
constructor of the base class. So, if the derived class is different from the
class T , the code doesn’t compile.

Solution to Problem Statement 3


(Case 1)#
1 // dispatchPolymorphism.cpp
2
3 #include <iostream>
4
5 struct Base{
6     virtual void interface(){
7         std::cout << "Implementation Base" << std::endl;
8     }
9 };
10
11 struct Derived1: Base{
12     virtual void interface(){
13         std::cout << "Implementation Derived1" << std::endl;
14     }
15 };
16
17 struct Derived2: Base{
18     virtual void interface(){
19         std::cout << "Implementation Derived2" << std::endl;
20     }
21 };
22
23 struct Derived3: Base{};
24
25 void execute(Base& base){
26     base.interface();
27 }
https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 7/14
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++
28
29 int main(){
30
31     std::cout << std::endl;
32
33     Derived1 d1;
34     Base& b1 = d1;
35     execute(b1);
36
37     Derived2 d2;
38     Base& b2 = d2;
39     execute(b2);
40
41     Derived3 d3;
42     Base& b3 = d3;
43     execute(b3);
44     
45     std::cout << std::endl;
46
47 }
48

Output 9.15s

Implementation Derived1

Implementation Derived2

Implementation Base

Explanation#
We have used dynamic polymorphism in the function template execute
(lines 25 – 27). This function only accepts a reference to the class object
passed. Now, we make objects of the derived classes and store references to
them (lines 34, 38 and 42). The static type of b1 , b2 , and b3 in lines 34, 38,
42 is Base and the dynamic type is Dervived1 , Derived2 , or Derived3
https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 8/14
3/20/22, 6:36 PM
y yp- Solutions - Generic Programming
, ,
Templates in C++

respectively.

Solution to Problem Statement 3


(Case 2)#
1 // dispatchGeneric.cpp
2
3 #include <iostream>
4
5 struct Base{
6     virtual void interface(){
7         std::cout << "Implementation Base" << std::endl;
8     }
9 };
10
11 struct Derived1: Base{
12     virtual void interface(){
13         std::cout << "Implementation Derived1" << std::endl;
14     }
15 };
16
17 struct Derived2: Base{
18     virtual void interface(){
19         std::cout << "Implementation Derived2" << std::endl;
20     }
21 };
22
23 struct Derived3: Base{};
24
25 template <typename T>
26 void execute(T& t){
27     t.interface();
28 }
29
30 int main(){
31     
32     std::cout << std::endl;
33     
34     Derived1 d1;
35     execute(d1);
36     
37     Derived2 d2;
38     execute(d2);
39     
40     Derived3 d3;
41     execute(d3);
42
https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 9/14
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++
42     
43     std::cout << std::endl;
44     
45 }
46

Output 1.66s

Implementation Derived1

Implementation Derived2

Implementation Base

Explanation#
We have used static polymorphism in the function template execute (line 25
– 27). The method execute accepts a reference. Now, we can make objects of
the derived classes and pass them to execute methods (line 34 – 41).

Solution to Problem Statement 3


(Case 3)#
1 // dispatchConcepts.cpp
2
3 #include <iostream>
4
5 template <typename T>
6 concept bool Interface(){
7     return requires(T a){
8         { a.interface } -> void;
9     };
10 }
https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 10/14
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++
10 }
11
12 struct Base{
13     virtual void interface(){
14         std::cout << "Implementation Base" << std::endl;
15     }
16 };
17
18 struct Derived1: Base{
19     virtual void interface(){
20         std::cout << "Implementation Derived1" << std::endl;
21     }
22 };
23
24 struct Derived2: Base{
25     virtual void interface(){
26         std::cout << "Implementation Derived2" << std::endl;
27     }
28 };
29
30 struct Derived3: Base{};
31
32 template <typename Interface>
33 void execute(Interface& inter){
34     inter.interface();
35 }
36
37 int main(){
38     
39     std::cout << std::endl;
40     
41     Derived1 d1;
42     execute(d1);
43     
44     Derived2 d2;
45     execute(d2);
46     
47     Derived3 d3;
48     execute(d3);
49     
50     std::cout << std::endl;
51     
52 }
53

https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 11/14
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++

Output 1.46s

Implementation Derived1

Implementation Derived2

Implementation Base

Explanation#
This implementation is based on concepts
(https://www.educative.io/collection/page/10370001/5799373671759872/5589
499255980032) which will be part of C++20. In the concrete case, concepts
mean that execute can only be invoked with types, which supports a
function with the name interface returning void .

Solution to Problem Statement 4#


1 // templatesCRTPShareMe.cpp
2
3 #include <iostream>
4 #include <memory>
5
6 class ShareMe: public std::enable_shared_from_this<ShareMe>{
7 public:
8   std::shared_ptr<ShareMe> getShared(){
9     return shared_from_this();
10   }
11 };
12
13 int main(){
14
15   std::cout << std::endl;
16
17 (/learn)
  // share the same ShareMe object
18   std::shared_ptr<ShareMe> shareMe(new ShareMe);
https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 12/14
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++
_p ( )
19   std::shared_ptr<ShareMe> shareMe1= shareMe->getShared();
20
21   // both resources have the same address
22   std::cout << "Address of resource of shareMe "<< (void*)shareMe.get() << " " << st
23   std::cout << "Address of resource of shareMe1 "<< (void*)shareMe1.get() << " " << 
24
25   // the use_count is 2
26   std::cout << "shareMe.use_count(): "<< shareMe.use_count() << std::endl;
27   std::cout << std::endl;
28
29 }

Output 1.62s

Address of resource of shareMe 0xf38c30

Address of resource of shareMe1 0xf38c30

shareMe.use_count(): 2

Explanation#
With the class std::enable_shared_from_this
(https://en.cppreference.com/w/cpp/memory/enable_shared_from_this), we
can create objects which return a std::shared_ptr on itself. For that, we
have to derive the class public from std::enable_shared_from_this . The
smart pointer shareMe (line 18) is copied by shareMe1 (line 19).
The call
shareMe->getShared() in line 19 creates a new smart pointer. getShared()
(line 8) internally uses the function shared_from_this . In lines 22 and 23,
shareMe.get() and shareMe.get() returns a pointer to the resource. In line
26, the shareMe.use_count() returns the value of the reference counter.

https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 13/14
3/20/22, 6:36 PM - Solutions - Generic Programming Templates in C++

In the next lesson, we’ll learn about expression templates.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercises Expression Templates

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/RLZmo9AyRYY 14/14
3/20/22, 6:37 PM Expression Templates - Generic Programming Templates in C++

Expression Templates
In this lesson, we'll study expression templates in detail.

We'll cover the following

• Expression Templates

• Lazy Evaluation
• A First Naive Approach

• The Issue
• The Solution

• The Idea

• The Entire Magic

Expression Templates#
Expression templates are “structures representing a computation at compile-
time, which are evaluated only as needed to produce efficient code for the
entire computation.”

Now we are at the center of lazy evaluation.

Lazy Evaluation#
The story about lazy evaluation in C++ is quite short. That will change in
C++20, with the ranges library from Eric Niebler. Lazy evaluation is the
default in Haskell. Lazy evaluation means that an expression is only
evaluated when needed
https://www.educative.io/courses/generic-templates-in-cpp/RMgr0XJ67LK 1/8
3/20/22, 6:37 PM Expression Templates - Generic Programming Templates in C++
evaluated when needed.

This strategy has two benefits.

Lazy evaluation helps you to save time and memory.


You can define an algorithm on infinite data structures. Of course, you
can only ask for a finite number of values at runtime.

Advantages:

Creates a domain-specific language (DSL)

Avoidance of temporary data structures

Disadvantages:

Longer compile-times
Advanced programming technique (template metaprogramming)

What problem do expression templates solve? Thanks to expression


templates, we can get rid of superfluous temporary objects in expressions.
What do we mean by superfluous temporary objects? To demonstrate that,
let’s look at the implementation of the class MyVector below.

A First Naive Approach#


MyVector is a simple wrapper for an std::vector<T> . The wrapper class has
two constructors (line 12 and 15), we have a size function which returns its
size (line 18 - 20), and the reading index operator (line 23 - 25) and writing
index access (line 27 - 29).

Given below is the naive vector implementation:

1 // vectorArithmeticOperatorOverloading.cpp
2
3 #include <iostream>
4 #include <vector>
https://www.educative.io/courses/generic-templates-in-cpp/RMgr0XJ67LK 2/8
3/20/22, 6:37 PM Expression Templates - Generic Programming Templates in C++
5
6 template<typename T>
7 class MyVector{
8   std::vector<T> cont;   
9
10 public:
11   // MyVector with initial size
12   MyVector(const std::size_t n) : cont(n){}  
13
14   // MyVector with initial size and value
15   MyVector(const std::size_t n, const double initialValue) : cont(n, initialValue){}
16   
17   // size of underlying container
18   std::size_t size() const{ 
19     return cont.size(); 
20   }
21
22   // index operators
23   T operator[](const std::size_t i) const{ 
24     return cont[i]; 
25   }
26
27   T& operator[](const std::size_t i){ 
28     return cont[i]; 
29   }
30
31 };
32
33 // function template for the + operator
34 template<typename T> 
35 MyVector<T> operator+ (const MyVector<T>& a, const MyVector<T>& b){
36   MyVector<T> result(a.size());
37   for (std::size_t s= 0; s <= a.size(); ++s){
38     result[s]= a[s]+b[s];
39   }
40   return result;
41 }
42
43 // function template for the * operator
44 template<typename T>
45 MyVector<T> operator* (const MyVector<T>& a, const MyVector<T>& b){
46    MyVector<T> result(a.size());
47   for (std::size_t s= 0; s <= a.size(); ++s){
48     result[s]= a[s]*b[s]; 
49   }
50   return result;
51 }
52
53 // function template for << operator
54 template<typename T>
55 std::ostream& operator<<(std::ostream& os, const MyVector<T>& cont){  
56   std::cout << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/RMgr0XJ67LK 3/8
3/20/22, 6:37 PM Expression Templates - Generic Programming Templates in C++
;
57   for (int i=0; i<cont.size(); ++i) {
58     os << cont[i] << ' ';
59   }
60   os << std::endl;
61   return os;
62 } 
63
64 int main(){
65
66   MyVector<double> x(10,5.4);
67   MyVector<double> y(10,10.3);
68
69   MyVector<double> result(10);
70   
71   result= x+x + y*y;
72   
73   std::cout << result << std::endl;
74   
75 }

Output 1.5s

116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89

Thanks to the overloaded + operator (line 34 - 41), the overloaded *


operator (line 44 - 51), and the overloaded output operator (line 54 - 62), the
objects x , y and result feel like numbers.

Why is this implementation naive? The answer is in the expression result =


x+x + y*y . In order to evaluate the expression, three temporary objects are
needed to hold the result of each arithmetic subexpression.

The Issue#
https://www.educative.io/courses/generic-templates-in-cpp/RMgr0XJ67LK 4/8
3/20/22, 6:37 PM Expression Templates - Generic Programming Templates in C++

  result = x+x + y*y; 

Arithmetic expressions create many temporary objects

The Solution#

The Idea#
https://www.educative.io/courses/generic-templates-in-cpp/RMgr0XJ67LK 5/8
3/20/22, 6:37 PM Expression Templates - Generic Programming Templates in C++

The overloaded operators return proxy objects

The final assignment result[i] = x[i] + x[i] + y[i] * y[i] triggers


the calculation

No temporary objects are necessary.

The Entire Magic#


result[i] = x[i] + x[i] + y[i] * y[i];

Thanks to the compiler explorer (https://godbolt.org/z/TXfimX) you can see


that no temporary objects are created. The expression is lazily evaluated in
place.

(/learn)

A sharp view at the previous screenshot helps to unwrap the magic. Let’s
have a look at the sequence of calls:

https://www.educative.io/courses/generic-templates-in-cpp/RMgr0XJ67LK 6/8
3/20/22, 6:37 PM Expression Templates - Generic Programming Templates in C++

In the next lesson, we’ll look at some examples of expression templates.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solutions - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/RMgr0XJ67LK 7/8
3/20/22, 6:37 PM Expression Templates - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/RMgr0XJ67LK 8/8
3/20/22, 6:38 PM - Examples - Generic Programming Templates in C++

- Examples
Let's have a look at some examples of expression templates.

We'll cover the following

• Example 1: Vector Arithmetic Based on Object-Orientation

• Explanation
• Example 2: Vector Arithmetic Based on Expression Templates

• Explanation

Example 1: Vector Arithmetic Based


on Object-Orientation#
1 // vectorArithmeticOperatorOverloading.cpp
2
3 #include <iostream>
4 #include <vector>
5
6 template<typename T>
7 class MyVector{
8   std::vector<T> cont;   
9
10 public:
11   // MyVector with initial size
12   explicit MyVector(const std::size_t n) : cont(n){}  
13
14   // MyVector with initial size and value
15   MyVector(const std::size_t n, const double initialValue) : cont(n, initialValue){}
16   
17   // size of underlying container
18   std::size_t size() const{ 
19     return cont.size(); 
20 }
https://www.educative.io/courses/generic-templates-in-cpp/RLy98qkEyrq 1/7
3/20/22, 6:38 PM - Examples - Generic Programming Templates in C++
20   }
21
22   // index operators
23   T operator[](const std::size_t i) const{ 
24     return cont[i]; 
25   }
26
27   T& operator[](const std::size_t i){ 
28     return cont[i]; 
29   }
30
31 };
32
33 // function template for the + operator
34 template<typename T> 
35 MyVector<T> operator+ (const MyVector<T>& a, const MyVector<T>& b){
36   MyVector<T> result(a.size());
37   for (std::size_t s= 0; s <= a.size(); ++s){
38     result[s]= a[s]+b[s];
39   }
40   return result;
41 }
42
43 // function template for the * operator
44 template<typename T>
45 MyVector<T> operator* (const MyVector<T>& a, const MyVector<T>& b){
46   MyVector<T> result(a.size());
47   for (std::size_t s= 0; s <= a.size(); ++s){
48     result[s]= a[s]*b[s]; 
49   }
50   return result;
51 }
52
53 // function template for << operator
54 template<typename T>
55 std::ostream& operator<<(std::ostream& os, const MyVector<T>& cont){  
56   os << std::endl;
57   for (std::size_t i=0; i<cont.size(); ++i) {
58     os << cont[i] << ' ';
59   }
60   return os;
61 } 
62
63 int main(){
64
65   MyVector<double> x(10,5.4);
66   MyVector<double> y(10,10.3);
67
68   MyVector<double> result(10);
69   
70   result= x+x + y*y;
71   
https://www.educative.io/courses/generic-templates-in-cpp/RLy98qkEyrq 2/7
3/20/22, 6:38 PM - Examples - Generic Programming Templates in C++
72   std::cout << result << std::endl;
73   
74 }
75

Output 2.13s

116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89

Explanation#
MyVector is a simple wrapper for an std::vector<T> . The wrapper class has
two constructors (line 12 and 15), we have a size function which returns its
size (line 18 - 20), and the reading index operator (line 23 - 25) and writing
index access (line 27 - 29).

Thanks to the overloaded + operator (line 34 - 41), the overloaded *


operator (line 44 - 51) and the overloaded output operator (line 54 - 61), the
objects x , y , and result feel like numbers on lines 70 and 72.

Example 2: Vector Arithmetic Based


on Expression Templates#
1 // vectorArithmeticExpressionTemplates.cpp
2
3 #include <cassert>
4 #include <iostream>
5 #include <vector>
6
7 template<typename T, typename Cont= std::vector<T> >
8 class MyVector{
https://www.educative.io/courses/generic-templates-in-cpp/RLy98qkEyrq 3/7
3/20/22, 6:38 PM - Examples - Generic Programming Templates in C++
8 class MyVector{
9   Cont cont;   
10
11 public:
12   // MyVector with initial size
13   MyVector(const std::size_t n) : cont(n){}
14
15   // MyVector with initial size and value
16   MyVector(const std::size_t n, const double initialValue) : cont(n, initialValue){}
17
18   // Constructor for underlying container
19   MyVector(const Cont& other) : cont(other){}
20
21   // assignment operator for MyVector of different type
22   template<typename T2, typename R2>
23   MyVector& operator=(const MyVector<T2, R2>& other){
24     assert(size() == other.size());
25     for (std::size_t i = 0; i < cont.size(); ++i) cont[i] = other[i];
26     return *this;
27   }
28
29   // size of underlying container
30   std::size_t size() const{ 
31     return cont.size(); 
32   }
33
34   // index operators
35   T operator[](const std::size_t i) const{ 
36     return cont[i]; 
37   }
38
39   T& operator[](const std::size_t i){ 
40     return cont[i]; 
41   }
42
43   // returns the underlying data
44   const Cont& data() const{ 
45     return cont; 
46   }
47
48   Cont& data(){ 
49     return cont; 
50   }
51 };
52
53 // MyVector + MyVector
54 template<typename T, typename Op1 , typename Op2>
55 class MyVectorAdd{
56   const Op1& op1;
57   const Op2& op2;
58
59 public:
https://www.educative.io/courses/generic-templates-in-cpp/RLy98qkEyrq 4/7
3/20/22, 6:38 PM - Examples - Generic Programming Templates in C++

60   MyVectorAdd(const Op1& a, const Op2& b): op1(a), op2(b){}
61
62   T operator[](const std::size_t i) const{ 
63     return op1[i] + op2[i]; 
64   }
65
66   std::size_t size() const{ 
67     return op1.size(); 
68   }
69 };
70
71 // elementwise MyVector * MyVector
72 template< typename T, typename Op1 , typename Op2 >
73 class MyVectorMul {
74   const Op1& op1;
75   const Op2& op2;
76
77 public:
78   MyVectorMul(const Op1& a, const Op2& b ): op1(a), op2(b){}
79
80   T operator[](const std::size_t i) const{ 
81     return op1[i] * op2[i]; 
82   }
83
84   std::size_t size() const{ 
85     return op1.size(); 
86   }
87 };
88
89 // function template for the + operator
90 template<typename T, typename R1, typename R2>
91 MyVector<T, MyVectorAdd<T, R1, R2> >
92 operator+ (const MyVector<T, R1>& a, const MyVector<T, R2>& b){
93   return MyVector<T, MyVectorAdd<T, R1, R2> >(MyVectorAdd<T, R1, R2 >(a.data(), b.da
94 }
95
96 // function template for the * operator
97 template<typename T, typename R1, typename R2>
98 MyVector<T, MyVectorMul< T, R1, R2> >
99 operator* (const MyVector<T, R1>& a, const MyVector<T, R2>& b){
100   return MyVector<T, MyVectorMul<T, R1, R2> >(MyVectorMul<T, R1, R2 >(a.data(), b.da
101 }
102
103 // function template for << operator
104 template<typename T>
105 std::ostream& operator<<(std::ostream& os, const MyVector<T>& cont){  
106   std::cout << std::endl;
107   for (int i=0; i<cont.size(); ++i) {
108     os << cont[i] << ' ';
109   }
110   os << std::endl;
111 return os;
https://www.educative.io/courses/generic-templates-in-cpp/RLy98qkEyrq 5/7
3/20/22, 6:38 PM - Examples - Generic Programming Templates in C++
111   return os;
112 } 
113
114 int main(){
115
116   MyVector<double> x(10,5.4);
117   MyVector<double> y(10,10.3);
118
119   MyVector<double> result(10);
120   
121   result= x+x + y*y;
122   
123   std::cout << result << std::endl;
124   
125 }

Output 1.56s
(/learn)

116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89 116.89

Explanation#
The key difference between the first naive implementation and this
implementation with expression templates is that the overloaded + and *
operators return in case of the expression tree proxy objects. These proxies
represent the expression tree (lines 91 and 98). The expression tree is only
created but not evaluated. Lazy, of course. The assignment operator (lines 22
- 27) triggers the evaluation of the expression tree that needs no temporary
objects.

In the next lesson, we’ll solve a few exercises for expression templates.
https://www.educative.io/courses/generic-templates-in-cpp/RLy98qkEyrq 6/7
3/20/22, 6:38 PM - Examples - Generic Programming Templates in C++

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Expression Templates - Exercises

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/RLy98qkEyrq 7/7
3/20/22, 6:39 PM - Exercises - Generic Programming Templates in C++

- Exercises
Let's solve a few exercises in this lesson regarding expression templates.

We'll cover the following

• Problem Statement 1

• Problem Statement 2

Problem Statement 1#
Compare both programs containing + and * operators and study, in
particular, the implementation based on expression templates.

Extend the example to expression templates by adding support


subtraction and the division operators for the MyVector class.

1 #include <iostream>
2 #include <vector>
3
4 template<typename T>
5 class MyVector{
6   std::vector<T> cont;   
7
8 public:
9   // MyVector with initial size
10   explicit MyVector(const std::size_t n) : cont(n){}  
11
12   // MyVector with initial size and value
13   MyVector(const std::size_t n, const double initialValue) : cont(n, initialValue){}
14   
15   // size of underlying container
16   std::size_t size() const{ 
17     return cont.size(); 
18   }
https://www.educative.io/courses/generic-templates-in-cpp/YV3wMxYKppp 1/6
3/20/22, 6:39 PM - Exercises - Generic Programming Templates in C++
18   }
19
20   // index operators
21   T operator[](const std::size_t i) const{ 
22     return cont[i]; 
23   }
24
25   T& operator[](const std::size_t i){ 
26     return cont[i]; 
27   }
28
29 };
30
31 // function template for the + operator
32 template<typename T> 
33 MyVector<T> operator+ (const MyVector<T>& a, const MyVector<T>& b){
34   MyVector<T> result(a.size());
35   for (std::size_t s= 0; s <= a.size(); ++s){
36     result[s]= a[s]+b[s];
37   }
38   return result;
39 }
40
41 // function template for the * operator
42 template<typename T>
43 MyVector<T> operator* (const MyVector<T>& a, const MyVector<T>& b){
44   MyVector<T> result(a.size());
45   for (std::size_t s= 0; s <= a.size(); ++s){
46     result[s]= a[s]*b[s]; 
47   }
48   return result;
49 }
50
51 // function template for << operator
52 template<typename T>
53 std::ostream& operator<<(std::ostream& os, const MyVector<T>& cont){  
54   std::cout << std::endl;
55   for (int i=0; i<cont.size(); ++i) {
56     os << cont[i] << ' ';
57   }
58   os << std::endl;
59   return os;
60 } 
61
62 // Implement subtraction and division operators here
63
64 int main(){
65   // call these subtraction and division operators here
66 }
67

https://www.educative.io/courses/generic-templates-in-cpp/YV3wMxYKppp 2/6
3/20/22, 6:39 PM - Exercises - Generic Programming Templates in C++

Problem Statement 2#
The solution of the previous example
(https://www.educative.io/collection/page/10370001/5799373671759872/5321
161208496128#example-2-vector-arithmetic-based-on-expression-templates)
Vector Arithmetic Expression Templates is too laborious. In particular, the
classes MyVectorAdd , MyVectorSub , MyVectorMul , and MyVectorDiv have a lot
in common. Try to simplify the program.

1 #include <cassert>
2 #include <iostream>
3 #include <vector>
4
5 template<typename T, typename Cont= std::vector<T> >
6 class MyVector{
7   Cont cont;   
8
9 public:
10   // MyVector with initial size
11   MyVector(const std::size_t n) : cont(n){}
12
13   // MyVector with initial size and value
14   MyVector(const std::size_t n, const double initialValue) : cont(n, initialValue){}
15
16   // Constructor for underlying container
17   MyVector(const Cont& other) : cont(other){}
18
19   // assignment operator for MyVector of different type
20   template<typename T2, typename R2>
21   MyVector& operator=(const MyVector<T2, R2>& other){
22     assert(size() == other.size());
23     for (std::size_t i = 0; i < cont.size(); ++i) cont[i] = other[i];
24     return *this;
25   }
26
27   // size of underlying container
28   std::size_t size() const{ 
29     return cont.size(); 
30   }
31
32 // i d t
https://www.educative.io/courses/generic-templates-in-cpp/YV3wMxYKppp 3/6
3/20/22, 6:39 PM - Exercises - Generic Programming Templates in C++
32   // index operators
33   T operator[](const std::size_t i) const{ 
34     return cont[i]; 
35   }
36
37   T& operator[](const std::size_t i){ 
38     return cont[i]; 
39   }
40
41   // returns the underlying data
42   const Cont& data() const{ 
43     return cont; 
44   }
45
46   Cont& data(){ 
47     return cont; 
48   }
49 };
50
51 // MyVector + MyVector
52 template<typename T, typename Op1 , typename Op2>
53 class MyVectorAdd{
54   const Op1& op1;
55   const Op2& op2;
56
57 public:
58   MyVectorAdd(const Op1& a, const Op2& b): op1(a), op2(b){}
59
60   T operator[](const std::size_t i) const{ 
61     return op1[i] + op2[i]; 
62   }
63
64   std::size_t size() const{ 
65     return op1.size(); 
66   }
67 };
68
69 // elementwise MyVector * MyVector
70 template< typename T, typename Op1 , typename Op2 >
71 class MyVectorMul {
72   const Op1& op1;
73   const Op2& op2;
74
75 public:
76   MyVectorMul(const Op1& a, const Op2& b ): op1(a),·op2(b){}
77
78 ··T·operator[](const·std::size_t·i)·const{·
79 ····return·op1[i]·*·op2[i];·
80 ··}
81
82 ··std::size_t·size()·const{·
83     return op1.size(); 
https://www.educative.io/courses/generic-templates-in-cpp/YV3wMxYKppp 4/6
3/20/22, 6:39 PM - Exercises - Generic Programming Templates in C++
p ();
84   }
85 };
86
87 // function template for the + operator
88 template<typename T, typename R1, typename R2>
89 MyVector<T, MyVectorAdd<T, R1, R2> >
90 operator+ (const MyVector<T, R1>& a, const MyVector<T, R2>& b){
91   return MyVector<T, MyVectorAdd<T, R1, R2> >(MyVectorAdd<T, R1, R2 >(a.data(), b.da
92 }
93
94 // function template for the * operator
95 template<typename T, typename R1, typename R2>
96 MyVector<T, MyVectorMul< T, R1, R2> >
97 operator* (const MyVector<T, R1>& a, const MyVector<T, R2>& b){
98   return MyVector<T, MyVectorMul<T, R1, R2> >(MyVectorMul<T, R1, R2 >(a.data(), b.da
99 }
100
101 // function template for < operator
102 template<typename T>
103 std::ostream& operator<<(std::ostream& os, const MyVector<T>& cont){  
104   std::cout << std::endl;
105   for (int i=0; i<cont.size(); ++i) {
106     os << cont[i] << ' ';
107   }
(/learn)
108   os << std::endl;
109   return os;
110 } 
111
112 int main(){
113 /*
114   MyVector<double> x(10,5.4);
115   MyVector<double> y(10,10.3);
116
117   MyVector<double> result(10);
118   
119   result= x+x + y*y;
120   
121   std::cout << result << std::endl;
122   */
123 }

In the next lesson, we’ll look at the solutions to these exercises.

https://www.educative.io/courses/generic-templates-in-cpp/YV3wMxYKppp 5/6
3/20/22, 6:39 PM - Exercises - Generic Programming Templates in C++

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Examples - Solutions

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/YV3wMxYKppp 6/6
3/20/22, 6:40 PM - Solutions - Generic Programming Templates in C++

- Solutions
Let's have a look at the solutions to the exercises we had in the last lesson.

We'll cover the following

• Problem Statement 1: Solution

• Explanation
• Problem Statement 2: Solution

• Explanation

Problem Statement 1: Solution#


1 // vectorArithmeticExpressionTemplates.cpp
2
3 #include <cassert>
4 #include <iostream>
5 #include <vector>
6
7 template<typename T, typename Cont= std::vector<T> >
8 class MyVector{
9   Cont cont;   
10
11 public:
12   // MyVector with initial size
13   explicit MyVector(const std::size_t n) : cont(n){}
14
15   // MyVector with initial size and value
16   MyVector(const std::size_t n, const double initialValue) : cont(n, initialValue){}
17
18   // Constructor for underlying container
19   explicit MyVector(const Cont& other) : cont(other){}
20
21   // assignment operator for MyVector of different type
22   template<typename T2, typename R2>
23 MyVector& operator (const MyVector<T2 R2>& other){
https://www.educative.io/courses/generic-templates-in-cpp/Bn2ooJP7RMY 1/9
3/20/22, 6:40 PM - Solutions - Generic Programming Templates in C++
23   MyVector& operator=(const MyVector<T2, R2>& other){
24     assert(size() == other.size());
25     for (std::size_t i = 0; i < cont.size(); ++i) cont[i] = other[i];
26     return *this;
27   }
28
29   // size of underlying container
30   std::size_t size() const{ 
31     return cont.size(); 
32   }
33
34   // index operators
35   T operator[](const std::size_t i) const{ 
36     return cont[i]; 
37   }
38
39   T& operator[](const std::size_t i){ 
40     return cont[i]; 
41   }
42
43   // returns the underlying data
44   const Cont& data() const{ 
45     return cont; 
46   }
47
48   Cont& data(){ 
49     return cont; 
50   }
51 };
52
53 // MyVector + MyVector
54 template<typename T, typename Op1 , typename Op2>
55 class MyVectorAdd{
56   const Op1& op1;
57   const Op2& op2;
58
59 public:
60   MyVectorAdd(const Op1& a, const Op2& b): op1(a), op2(b){}
61
62   T operator[](const std::size_t i) const{ 
63     return op1[i] + op2[i]; 
64   }
65
66   std::size_t size() const{ 
67     return op1.size(); 
68   }
69 };
70
71 // MyVector - MyVector
72 template<typename T, typename Op1, typename Op2>
73 class MyVectorSub {
74   const Op1& op1;
https://www.educative.io/courses/generic-templates-in-cpp/Bn2ooJP7RMY 2/9
3/20/22, 6:40 PM - Solutions - Generic Programming Templates in C++

75   const Op2& op2;
76
77 public:
78   MyVectorSub(const Op1& a, const Op2& b) : op1(a), op2(b) {}
79
80   T operator[](const std::size_t i) const {
81     return op1[i] - op2[i];
82   }
83
84   std::size_t size() const {
85     return op1.size();
86   }
87 };
88
89 // elementwise MyVector * MyVector
90 template< typename T, typename Op1 , typename Op2 >
91 class MyVectorMul {
92   const Op1& op1;
93   const Op2& op2;
94
95 public:
96   MyVectorMul(const Op1& a, const Op2& b ): op1(a), op2(b){}
97
98   T operator[](const std::size_t i) const{ 
99     return op1[i] * op2[i]; 
100   }
101
102   std::size_t size() const{ 
103     return op1.size(); 
104   }
105 };
106
107 // elementwise MyVector / MyVector
108 template< typename T, typename Op1, typename Op2 >
109 class MyVectorDiv {
110   const Op1& op1;
111   const Op2& op2;
112
113 public:
114   MyVectorDiv(const Op1& a, const Op2& b) : op1(a), op2(b) {}
115
116   T operator[](const std::size_t i) const {
117     return op1[i] / op2[i];
118   }
119
120   std::size_t size() const {
121     return op1.size();
122   }
123 };
124
125 // function template for the + operator
126 template<typename T typename R1 typename R2>
https://www.educative.io/courses/generic-templates-in-cpp/Bn2ooJP7RMY 3/9
3/20/22, 6:40 PM - Solutions - Generic Programming Templates in C++
126 template<typename T, typename R1, typename R2>
127 MyVector<T, MyVectorAdd<T, R1, R2> >
128 operator+ (const MyVector<T, R1>& a, const MyVector<T, R2>& b){
129   return MyVector<T, MyVectorAdd<T, R1, R2> >(MyVectorAdd<T, R1, R2 >(a.data(), b.da
130 }
131
132 // function template for the - operator
133 template<typename T, typename R1, typename R2>
134 MyVector<T, MyVectorSub<T, R1, R2> >
135 operator- (const MyVector<T, R1>& a, const MyVector<T, R2>& b) {
136   return MyVector<T, MyVectorSub<T, R1, R2> >(MyVectorSub<T, R1, R2 >(a.data(), b.da
137 }
138
139 // function template for the * operator
140 template<typename T, typename R1, typename R2>
141 MyVector<T, MyVectorMul< T, R1, R2> >
142 operator* (const MyVector<T, R1>& a, const MyVector<T, R2>& b){
143   return MyVector<T, MyVectorMul<T, R1, R2> >(MyVectorMul<T, R1, R2 >(a.data(), b.da
144 }
145
146 // function template for the / operator
147 template<typename T, typename R1, typename R2>
148 MyVector<T, MyVectorDiv< T, R1, R2> >
149 operator/ (const MyVector<T, R1>& a, const MyVector<T, R2>& b) {
150   return MyVector<T, MyVectorDiv<T, R1, R2> >(MyVectorDiv<T, R1, R2 >(a.data(), b.da
151 }
152
153 // function template for < operator
154 template<typename T>
155 std::ostream& operator<<(std::ostream& os, const MyVector<T>& cont){  
156   std::cout << std::endl;
157   for (int i=0; i<cont.size(); ++i) {
158     os << cont[i] << ' ';
159   }
160   os << std::endl;
161   return os;
162 } 
163
164 int main(){
165
166   MyVector<double> x(10,5.4);
167   MyVector<double> y(10,10.3);
168
169   MyVector<double> result(10);
170   
171   result = x + x + y * y - x + x + y / y;
172   
173   std::cout << result << std::endl;
174   
175 }
176

https://www.educative.io/courses/generic-templates-in-cpp/Bn2ooJP7RMY 4/9
3/20/22, 6:40 PM - Solutions - Generic Programming Templates in C++

Output 1.54s

117.89 117.89 117.89 117.89 117.89 117.89 117.89 117.89 117.89 117.89

Explanation#
We have implemented the overloaded - operator (line 133 - 137), the
overloaded / operator (line 147 - 151), and the overloaded output operator
(line 154 - 162). Now, the objects x , y , and result feel like numbers.

Problem Statement 2: Solution#


1 #include <cassert>
2 #include <functional>
3 #include <iostream>
4 #include <vector>
5
6 template<typename T, typename Cont= std::vector<T> >
7 class MyVector{
8   Cont cont;   
9
10 public:
11   // MyVector with initial size
12   explicit MyVector(const std::size_t n) : cont(n){}
13
14   // MyVector with initial size and value
15   MyVector(const std::size_t n, const double initialValue) : cont(n, initialValue){}
16
17   // Constructor for underlying container
18   explicit MyVector(const Cont& other) : cont(other){}
19
20 // assignment operator for MyVector of different type
https://www.educative.io/courses/generic-templates-in-cpp/Bn2ooJP7RMY 5/9
3/20/22, 6:40 PM - Solutions - Generic Programming Templates in C++
20   // assignment operator for MyVector of different type
21   template<typename T2, typename R2>
22   MyVector& operator=(const MyVector<T2, R2>& other){
23     assert(size() == other.size());
24     for (std::size_t i = 0; i < cont.size(); ++i) cont[i] = other[i];
25     return *this;
26   }
27
28   // size of underlying container
29   std::size_t size() const{ 
30     return cont.size(); 
31   }
32
33   // index operators
34   T operator[](const std::size_t i) const{ 
35     return cont[i]; 
36   }
37
38   T& operator[](const std::size_t i){ 
39     return cont[i]; 
40   }
41
42   // returns the underlying data
43   const Cont& data() const{ 
44     return cont; 
45   }
46
47   Cont& data(){ 
48     return cont; 
49   }
50 };
51
52 template<template<typename> class Oper, typename T, typename Op1 , typename Op2>
53 class MyVectorCalc{
54   const Op1& op1;
55   const Op2& op2;
56   Oper<T> oper;
57
58 public:
59   MyVectorCalc(const Op1& a, const Op2& b): op1(a), op2(b) {}
60
61   T operator[](const std::size_t i) const{ 
62     
63     return oper(op1[i], op2[i]); 
64   }
65
66   std::size_t size() const{ 
67     return op1.size(); 
68   }
69 };
70
71 // function template for the + operator
https://www.educative.io/courses/generic-templates-in-cpp/Bn2ooJP7RMY 6/9
3/20/22, 6:40 PM - Solutions - Generic Programming Templates in C++

72 template<typename T, typename R1, typename R2>
73 MyVector<T, MyVectorCalc<std::plus, T, R1, R2> >
74 operator+ (const MyVector<T, R1>& a, const MyVector<T, R2>& b){
75   return MyVector<T, MyVectorCalc<std::plus, T, R1, R2> >(MyVectorCalc<std::plus, T,
76 }
77
78 // function template for the - operator
79 template<typename T, typename R1, typename R2>
80 MyVector<T, MyVectorCalc<std::minus, T, R1, R2> >
81 operator- (const MyVector<T, R1>& a, const MyVector<T, R2>& b) {
82   return MyVector<T, MyVectorCalc<std::minus, T, R1, R2> >(MyVectorCalc<std::minus, 
83 }
84
85 // function template for the * operator
86 template<typename T, typename R1, typename R2>
87 MyVector<T, MyVectorCalc<std::multiplies, T, R1, R2> >
88 operator* (const MyVector<T, R1>& a, const MyVector<T, R2>& b){
89   return MyVector<T, MyVectorCalc<std::multiplies, T, R1, R2> >(MyVectorCalc<std::mu
90 }
91
92 // function template for the / operator
93 template<typename T, typename R1, typename R2>
94 MyVector<T, MyVectorCalc<std::divides, T, R1, R2> >
95 operator/ (const MyVector<T, R1>& a, const MyVector<T, R2>& b) {
96   return MyVector<T, MyVectorCalc<std::divides, T, R1, R2> >(MyVectorCalc<std::divid
97 }
98
99 // function template for << operator
100 template<typename T>
101 std::ostream& operator<<(std::ostream& os, const MyVector<T>& cont){  
102   std::cout << std::endl;
103   for (int i=0; i<cont.size(); ++i) {
104     os << cont[i] << ' ';
105   }
106   os << std::endl;
107   return os;
108 } 
109
110 int main(){
111
112   MyVector<double> x(10,5.4);
113   MyVector<double> y(10,10.3);
114
115   MyVector<double> result(10);
116   
117   result = x + x + y * y - x + x + y / y;
118   
119   std::cout << result << std::endl;
120   
121 }
122

https://www.educative.io/courses/generic-templates-in-cpp/Bn2ooJP7RMY 7/9
3/20/22, 6:40 PM - Solutions - Generic Programming Templates in C++

Output 2.52s

117.89 117.89 117.89 117.89 117.89 117.89 117.89 117.89 117.89 117.89

(/learn)

Explanation#
In contrast to the previous example
(https://www.educative.io/collection/page/10370001/5799373671759872/5321
161208496128#example-2-vector-arithmetic-based-on-expression-templates),
in which each arithmetic operation such as addition ( MyVectorAdd ),
subtraction ( MyVectorSub ), multiplication ( MyVectorMult ), or division
( MyVectorDiv ) is represented in a type, this improved version uses a generic
binary operator ( MyVectorCalc ) in lines 52 – 69. This generic binary operator
requires the concrete binary operator such as std::plus to become the
concrete binary operator. The predefined function objects
(https://en.cppreference.com/w/cpp/utility/functional) std::plus ,
std::minus , std::multiplies , and std::divides are part of the standard
template library. You can think of them as a lambda-function representing
the requested operation.

In the next lesson, we’ll study policy and traits in idioms and patterns.

Interviewing soon? We've partnered with Hired so that companies apply to


https://www.educative.io/courses/generic-templates-in-cpp/Bn2ooJP7RMY 8/9
Interviewing soon? We ve partnered with Hired so that companies apply to
3/20/22, 6:40 PM - Solutions - Generic Programming Templates in C++

you instead of you applying to them. See how

(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercises Idioms and Patterns: Policy and Traits

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/Bn2ooJP7RMY 9/9
3/20/22, 6:41 PM Idioms and Patterns: Policy and Traits - Generic Programming Templates in C++

Idioms and Patterns: Policy and Traits


In this lesson, we will study about policy and traits in idioms and patterns.

We'll cover the following

• Policy and Traits

• Policy
• Traits

Policy and Traits#


Policy#
A Policy is a generic function or class with adaptable behavior.

Policy parameters have typically default values.

This adaptable behavior is expressed in several type parameters, the so-


called policy parameters. Due to different policy parameters, the concrete
generic function or class behaves differently.

Typical examples for policies are the containers of the Standard Template
Library such as std::vector , or std::unordered_map :

std::vector has a default policy for allocating memory, which is based


on the type of the element: std::allocator<T>
https://www.educative.io/courses/generic-templates-in-cpp/YMNvvpWGrAK 1/3
3/20/22, 6:41 PM Idioms and Patterns: Policy and Traits - Generic Programming Templates in C++

std::unordered_map has a default policy for generating the hash value


( std::hash<Key> ), comparing two keys ( std::equal_to<Key> ), and
allocating memory ( std::allocator<std::pair<const Key, T> ). The hash
function and the comparison function are based on the key.

template<class T, class Allocator = std::allocator<T>>

class vector;

template<

   class Key,

   class T,

   class Hash = std::hash<Key>,

   class KeyEqual = std::equal_to<Key>,

   class Allocator = std::allocator<std::pair<const Key, T>>>

class unordered_map;

Traits#
(/learn)

Traits are class templates, which provide characteristics of a generic type.

template< class T >

struct is_integral;

template<T>

struct iterator_traits<T*> {

  using difference_type = std::ptrdiff_t; 

  using value_type = T;

  using pointer = T*;

  using reference = T&;

  using iterator_category = std::random_access_iterator_tag;

};

Traits can extract one or more characteristics of a class template.

The function std::is_integral<T> from the type-traits library


determines, if T is an integral type.
https://www.educative.io/courses/generic-templates-in-cpp/YMNvvpWGrAK 2/3
3/20/22, 6:41 PM Idioms and Patterns: Policy and Traits - Generic Programming Templates in C++
determines, if T is an integral type.

In the next lesson, we’ll look at a few examples of policy and traits in idioms
and patterns.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solutions - Examples

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/YMNvvpWGrAK 3/3
3/20/22, 6:42 PM - Examples - Generic Programming Templates in C++

- Examples
Let's have a look at the examples of policy and traits in this lesson.

We'll cover the following

• Example 1: Templates Policy

• Explanation
• Example 2: Templates Traits

• Explanation

Example 1: Templates Policy#


1 // PolicytemplatesPolicy.cpp
2
3 #include <iostream>
4 #include <unordered_map>
5
6 struct MyInt{
7     explicit MyInt(int v):val(v){}
8     int val;
9 };
10
11 struct MyHash{
12     std::size_t operator()(MyInt m) const {
13         std::hash<int> hashVal;
14         return hashVal(m.val);
15     }
16 };
17
18 struct MyEqual{
19     bool operator () (const MyInt& fir, const MyInt& sec) const {
20         return fir.val == sec.val;
21     }
22 };
23
https://www.educative.io/courses/generic-templates-in-cpp/YM0MpgJ8r69 1/5
3/20/22, 6:42 PM - Examples - Generic Programming Templates in C++
23
24 std::ostream& operator << (std::ostream& strm, const MyInt& myIn){
25     strm << "MyInt(" << myIn.val << ")";
26     return strm;
27 }
28
29 int main(){
30
31     std::cout << std::endl;
32
33     typedef std::unordered_map<MyInt, int, MyHash, MyEqual> MyIntMap;
34
35     std::cout << "MyIntMap: ";
36     MyIntMap myMap{{MyInt(-2), -2}, {MyInt(-1), -1}, {MyInt(0), 0}, {MyInt(1), 1}};
37
38     for(auto m : myMap) std::cout << '{' << m.first << ", " << m.second << "}";
39
40     std::cout << "\n\n";
41
42 }
43

Output 1.45s

MyIntMap: {MyInt(1), 1}{MyInt(0), 0}{MyInt(-1), -1}{MyInt(-2), -2}

Explanation#
The example uses the user-defined type MyInt as key for an
std:unordered_map . To use MyInt as a key, MyInt must support the hash
value and must be equal comparable. The classes MyHash (lines 11 – 16) and
MyEqual (lines 18 – 22) provides the functionality for MyInt by delegating the
job to the underlying int . The typedef in line 33 brings all together. In line
36 i d k i
https://www.educative.io/courses/generic-templates-in-cpp/YM0MpgJ8r69 Th l 2/5
3/20/22, 6:42 PM - Examples - Generic Programming Templates in C++

36, MyInt is used as a key in a std::unordered_map . The class

std::unoredered_map in line 33 is an example of the policy class. The


adaptable behavior is, in this case, the hash
function and the equal function.
Both policy parameters have default but can also be specified.

Example 2: Templates Traits#


1 // TemplatesTraits.cpp
2
3 #include <iostream>
4 #include <type_traits>
5
6 using namespace std;
7
8 template <typename T>
9 void getPrimaryTypeCategory(){
10
11   cout << boolalpha << endl;
12
13   cout << "is_void<T>::value: " << is_void<T>::value << endl;
14   cout << "is_integral<T>::value: " << is_integral<T>::value << endl;
15   cout << "is_floating_point<T>::value: " << is_floating_point<T>::value << endl;
16   cout << "is_array<T>::value: " << is_array<T>::value << endl;
17   cout << "is_pointer<T>::value: " << is_pointer<T>::value << endl;
18   cout << "is_reference<T>::value: " << is_reference<T>::value << endl;
19   cout << "is_member_object_pointer<T>::value: " << is_member_object_pointer<T>::val
20   cout << "is_member_function_pointer<T>::value: " << is_member_function_pointer<T>:
21   cout << "is_enum<T>::value: " << is_enum<T>::value << endl;
22   cout << "is_union<T>::value: " << is_union<T>::value << endl;
23   cout << "is_class<T>::value: " << is_class<T>::value << endl;
24   cout << "is_function<T>::value: " << is_function<T>::value << endl;
25   cout << "is_lvalue_reference<T>::value: " << is_lvalue_reference<T>::value << endl
26   cout << "is_rvalue_reference<T>::value: " << is_rvalue_reference<T>::value << endl
27
28   cout << endl;
29
30 }
31
32 int main(){
33   getPrimaryTypeCategory<void>();
34 }
35

https://www.educative.io/courses/generic-templates-in-cpp/YM0MpgJ8r69 3/5
3/20/22, 6:42 PM - Examples - Generic Programming Templates in C++

(/learn)
Output 1.5s

is_void<T>::value: true

is_integral<T>::value: false

is_floating_point<T>::value: false

is_array<T>::value: false

is_pointer<T>::value: false

is_reference<T>::value: false

is_member_object_pointer<T>::value: false

is_member_function_pointer<T>::value: false

Explanation#
In the example above, we have defined the function getPrimaryTypeCategory
in line 9 which takes a type T and determines which type category T
belongs to. This example uses all 14 primary type categories of the type-traits
library.

In the next lesson, we’ll solve a few exercises to understand more on policy
and traits in idioms and patterns.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

https://www.educative.io/courses/generic-templates-in-cpp/YM0MpgJ8r69 4/5
3/20/22, 6:42 PM - Examples - Generic Programming Templates in C++

Back Next

Idioms and Patterns: Policy and Traits - Exercises

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/YM0MpgJ8r69 5/5
3/20/22, 6:42 PM - Exercises - Generic Programming Templates in C++

- Exercises
Let's solve a few exercises on policy and traits in this lesson.

We'll cover the following

• Problem Statement 1

• Problem Statement 2
• Problem Statement 3

Problem Statement 1#
Extend the example
(https://www.educative.io/collection/page/10370001/5799373671759872/5116
113329324032#example-1-templates-policy) below in such a way such that
the type MyInt can be used as a key to an std::map .

1 // PolicytemplatesPolicy.cpp
2
3 #include <iostream>
4 #include <unordered_map>
5
6 struct MyInt{
7     explicit MyInt(int v):val(v){}
8     int val;
9 };
10
11 struct MyHash{
12     std::size_t operator()(MyInt m) const {
13         std::hash<int> hashVal;
14         return hashVal(m.val);
15     }
16 };
17
https://www.educative.io/courses/generic-templates-in-cpp/Y5RrPKjOyvA 1/5
3/20/22, 6:42 PM - Exercises - Generic Programming Templates in C++
17
18 struct MyEqual{
19     bool operator () (const MyInt& fir, const MyInt& sec) const {
20         return fir.val == sec.val;
21     }
22 };
23
24 std::ostream& operator << (std::ostream& strm, const MyInt& myIn){
25     strm << "MyInt(" << myIn.val << ")";
26     return strm;
27 }
28
29 // write your functions here
30
31 int main(){
32
33 // uncomment these line after implementing these functionalities
34
35 /*
36     std::cout << std::endl;
37
38     typedef std::unordered_map<MyInt, int, MyHash, MyEqual> MyUnorderedMap;
39
40     std::cout << "MyUnorderedMap: ";
41     MyUnorderedMap myMap{{MyInt(-2), -2}, {MyInt(-1), -1}, {MyInt(0), 0}, {MyInt(1),
42
43     for(auto m : myMap) std::cout << '{' << m.first << ", " << m.second << "}";
44
45     std::cout << std::endl;
46     
47     typedef std::map<MyInt, int, MySmaller> MyOrderedMap;
48     
49     std::cout << "MyOrderedMap: ";
50     MyOrderedMap myMap2{{MyInt(-2), -2}, {MyInt(-1), -1}, {MyInt(0), 0}, {MyInt(1), 
51     
52     for(auto m : myMap2) std::cout << '{' << m.first << ", " << m.second << "}";
53
54     std::cout << "\n\n";
55 */
56 }

Problem Statement 2#
https://www.educative.io/courses/generic-templates-in-cpp/Y5RrPKjOyvA 2/5
3/20/22, 6:42 PM - Exercises - Generic Programming Templates in C++

Define a std::map<std::string, int> , in which the keys are sorted in a


decreasing way.

1 #include <iostream>
2 #include <map>
3
4 int main() {
5   
6   // your code goes here
7   
8 }

Problem Statement 3#
The function template templateTraits.cpp
(https://www.educative.io/collection/page/10370001/5799373671759872/5116
113329324032#example-2-templates-traits) shows for which primary type
category each type belongs to. Each type is in exactly one primary type
category. Extend the program so that you get a type for each type category.

1 // TemplatesTraits.cpp
2
3 #include <iostream>
4 #include <type_traits>
5
6 using namespace std;
7
8 template <typename T>
9 void getPrimaryTypeCategory(){
10
11   cout << boolalpha << endl;
12 (/learn)
13   cout << "is_void<T>::value: " << is_void<T>::value << endl;
14   cout << "is_integral<T>::value: " << is_integral<T>::value << endl;
15   cout << "is_floating_point<T>::value: " << is_floating_point<T>::value << endl;
https://www.educative.io/courses/generic-templates-in-cpp/Y5RrPKjOyvA 3/5
3/20/22, 6:42 PM - Exercises - Generic Programming Templates in C++

16   cout << "is_array<T>::value: " << is_array<T>::value << endl;
17   cout << "is_pointer<T>::value: " << is_pointer<T>::value << endl;
18   cout << "is_reference<T>::value: " << is_reference<T>::value << endl;
19   cout << "is_member_object_pointer<T>::value: " << is_member_object_pointer<T>::val
20   cout << "is_member_function_pointer<T>::value: " << is_member_function_pointer<T>:
21   cout << "is_enum<T>::value: " << is_enum<T>::value << endl;
22   cout << "is_union<T>::value: " << is_union<T>::value << endl;
23   cout << "is_class<T>::value: " << is_class<T>::value << endl;
24   cout << "is_function<T>::value: " << is_function<T>::value << endl;
25   cout << "is_lvalue_reference<T>::value: " << is_lvalue_reference<T>::value << endl
26   cout << "is_rvalue_reference<T>::value: " << is_rvalue_reference<T>::value << endl
27
28   cout << endl;
29
30 }
31
32 int main(){
33   // check for all types for calling type-traits fucntions
34   
35 }

We’ll look at the solutions of these exercises in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Examples - Solutions

Mark as Completed
https://www.educative.io/courses/generic-templates-in-cpp/Y5RrPKjOyvA 4/5
3/20/22, 6:42 PM - Exercises - Generic Programming Templates in C++
Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/Y5RrPKjOyvA 5/5
3/20/22, 6:46 PM - Solutions - Generic Programming Templates in C++

- Solutions
Let's look at the solution reviews of previously solved exercises.

We'll cover the following

• Solution Review of Problem Statement 1

• Explanation
• Solution Review of Problem Statement 2

• Explanation
• Solution Review of Problem Statement 3

• Explanation

Solution Review of Problem


Statement 1#
1 // templatePolicyMap.cpp
2
3 #include <iostream>
4 #include <map>
5 #include <unordered_map>
6
7 struct MyInt{
8     explicit MyInt(int v):val(v){}
9     int val;
10 };
11
12 struct MyHash{
13     std::size_t operator()(MyInt m) const {
14         std::hash<int> hashVal;
15         return hashVal(m.val);
16     }
https://www.educative.io/courses/generic-templates-in-cpp/3j9Rp85JBV4 1/7
3/20/22, 6:46 PM - Solutions - Generic Programming Templates in C++
16     }
17 };
18
19 struct MyEqual{
20     bool operator () (const MyInt& fir, const MyInt& sec) const {
21         return fir.val == sec.val;
22     }
23 };
24
25 struct MySmaller{
26     bool operator () (const MyInt& fir, const MyInt& sec) const {
27         return fir.val < sec.val;
28     }
29     
30 };
31
32 std::ostream& operator << (std::ostream& strm, const MyInt& myIn){
33     strm << "MyInt(" << myIn.val << ")";
34     return strm;
35 }
36
37 int main(){
38
39     std::cout << std::endl;
40
41     typedef std::unordered_map<MyInt, int, MyHash, MyEqual> MyUnorderedMap;
42
43     std::cout << "MyUnorderedMap: ";
44     MyUnorderedMap myMap{{MyInt(-2), -2}, {MyInt(-1), -1}, {MyInt(0), 0}, {MyInt(1),
45
46     for(auto m : myMap) std::cout << '{' << m.first << ", " << m.second << "}";
47
48     std::cout << std::endl;
49     
50     typedef std::map<MyInt, int, MySmaller> MyOrderedMap;
51     
52     std::cout << "MyOrderedMap: ";
53     MyOrderedMap myMap2{{MyInt(-2), -2}, {MyInt(-1), -1}, {MyInt(0), 0}, {MyInt(1), 
54     
55     for(auto m : myMap2) std::cout << '{' << m.first << ", " << m.second << "}";
56
57     std::cout << "\n\n";
58
59 }
60

https://www.educative.io/courses/generic-templates-in-cpp/3j9Rp85JBV4 2/7
3/20/22, 6:46 PM - Solutions - Generic Programming Templates in C++

Output 2.11s

MyUnorderedMap: {MyInt(1), 1}{MyInt(0), 0}{MyInt(-1), -1}{MyInt(-2), -2}

MyOrderedMap: {MyInt(-2), -2}{MyInt(-1), -1}{MyInt(0), 0}{MyInt(1), 1}

Explanation#
In order to use MyInt as a key in an std::map , MyInt has to support an
ordering. The class MySmaller supports ordering on MyInt . The typedef in
line 50 allows us to use MyInt as a key (line 53) in MyOrderedMap .

Solution Review of Problem


Statement 2#
1 // templatePolicyDecreasing.cpp
2
3 #include <iostream>
4 #include <map>
5
6
7 int main(){
8
9     std::cout << std::endl;
10     
11     std::map<std::string, int, std::greater<std::string>> myDecreaseMap{{"Grimm", 1}
12
13     std::cout << "myDecreaseMap: ";
14     for(auto m : myDecreaseMap) std::cout << '{' << m.first << ", " << m.second << "
15
16     std::cout << "\n\n";
17
18 }
19
https://www.educative.io/courses/generic-templates-in-cpp/3j9Rp85JBV4 3/7
3/20/22, 6:46 PM - Solutions - Generic Programming Templates in C++

Output 1.41s

myDecreaseMap: {Schmitt, 3}{Meyer, -2}{Huber, 2}{Grimm, 1}

Explanation#
In the above example, we have stored in line 11 the keys in increasing order
in the std::map . In line 14, we have used for loop to print the element
stored in the myDecreaseMap .

Solution Review of Problem


Statement 3#
1 // TemplateTraitsPrimary.cpp
2
3 #include <iostream>
4 #include <type_traits>
5
6 using namespace std;
7
8 template <typename T>
9 void getPrimaryTypeCategory(){
10
11   cout << boolalpha << endl;
12
13   cout << "is_void<T>::value: " << is_void<T>::value << endl;
14   cout << "is_integral<T>::value: " << is_integral<T>::value << endl;
15   cout << "is_floating_point<T>::value: " << is_floating_point<T>::value << endl;
https://www.educative.io/courses/generic-templates-in-cpp/3j9Rp85JBV4 4/7
3/20/22, 6:46 PM - Solutions - Generic Programming Templates in C++
_ g_p _ g_p ;
16   cout << "is_array<T>::value: " << is_array<T>::value << endl;
17   cout << "is_pointer<T>::value: " << is_pointer<T>::value << endl;
18   cout << "is_reference<T>::value: " << is_reference<T>::value << endl;
19   cout << "is_member_object_pointer<T>::value: " << is_member_object_pointer<T>::val
20   cout << "is_member_function_pointer<T>::value: " << is_member_function_pointer<T>:
21   cout << "is_enum<T>::value: " << is_enum<T>::value << endl;
22   cout << "is_union<T>::value: " << is_union<T>::value << endl;
23   cout << "is_class<T>::value: " << is_class<T>::value << endl;
24   cout << "is_function<T>::value: " << is_function<T>::value << endl;
25   cout << "is_lvalue_reference<T>::value: " << is_lvalue_reference<T>::value << endl
26   cout << "is_rvalue_reference<T>::value: " << is_rvalue_reference<T>::value << endl
27
28   cout << endl;
29
30 }
31
32 int main(){
33     
34     getPrimaryTypeCategory<void>();
35     getPrimaryTypeCategory<short>();
36     getPrimaryTypeCategory<double>();
37     getPrimaryTypeCategory<int []>();
38     getPrimaryTypeCategory<int*>();
39     getPrimaryTypeCategory<int&>();
40     struct A{
41         int a;
42         int f(double){return 2011;}
43     };
44     getPrimaryTypeCategory<int A::*>();
45     getPrimaryTypeCategory<int (A::*)(double)>();
46     enum E{
47         e= 1,
48     };
49     getPrimaryTypeCategory<E>();
50     union U{
51       int u;
52     };
53     getPrimaryTypeCategory<U>();
54     getPrimaryTypeCategory<string>();
55     getPrimaryTypeCategory<int * (double)>();
56     getPrimaryTypeCategory<int&>();
57     getPrimaryTypeCategory<int&&>();
58     
59 }
60
(/learn)

https://www.educative.io/courses/generic-templates-in-cpp/3j9Rp85JBV4 5/7
3/20/22, 6:46 PM - Solutions - Generic Programming Templates in C++

Output 3.24s

is_void<T>::value: true

is_integral<T>::value: false

is_floating_point<T>::value: false

is_array<T>::value: false

is_pointer<T>::value: false

is_reference<T>::value: false

is_member_object_pointer<T>::value: false

is_member_function_pointer<T>::value: false

Explanation#
In the example mentioned above, we have defined the function
getPrimaryTypeCategory in line 9 which takes the built-in type of C++ and
returns true in front of the type we have defined in lines (13 – 26). We’re
checking for each type by passing the type in the function.

Let’s move on to tag dispatching in idioms and patterns in the next lesson.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercises Idioms and Patterns: Tag Dispatching


https://www.educative.io/courses/generic-templates-in-cpp/3j9Rp85JBV4 6/7
3/20/22, 6:46 PM - Solutions - Generic Programming Templates in C++
Exercises Idioms and Patterns: Tag Dispatching

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/3j9Rp85JBV4 7/7
3/20/22, 6:46 PM Idioms and Patterns: Tag Dispatching - Generic Programming Templates in C++

Idioms and Patterns: Tag Dispatching


In this lesson, we'll learn about tag dispatching in idioms and patterns.

We'll cover the following

• Tag Dispatching

Tag Dispatching#
Tag Dispatching enables us to choose a function based on type
characteristics.

The decision takes place at compile-time.


Traits make the decision based on specific properties of an argument.
(/learn)
The main benefit is performance.

The iterator categories from the Standard Template Library are a typical
use-case:

struct input_iterator_tag{};

struct output_iterator_tag{};

struct forward_iterator_tag: public input_iterator_tag{};

struct bidirectional_iterator_tag: public forward_iterator_tag{}; 

struct random_access_iterator_tag: public bidirectional_iterator_tag{};

In the concrete case, std::random_access_iterator is a refinement of


std::bidirectional_iterator , std::birectional_iterator is a refinement of
std::forward_iterator , and std::forward_iterator is a refinement of
std::input iterator
https://www.educative.io/courses/generic-templates-in-cpp/3jmLBpA223M 1/2
3/20/22, 6:46 PM Idioms and Patterns: Tag Dispatching - Generic Programming Templates in C++
std::input_iterator .

In the next lesson, we’ll look at an example of tag dispatching in idioms and
patterns.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solutions - Example

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/3jmLBpA223M 2/2
3/20/22, 6:47 PM - Example - Generic Programming Templates in C++

- Example
Let's have a look at an example of tag dispatching.

We'll cover the following

• Example: Templates Tag Dispatching

• Explanation

Example: Templates Tag Dispatching#


1 // TemplatesTagDispatching.cpp
2
3 #include <iterator>
4 #include <forward_list>
5 #include <list>
6 #include <vector>
7 #include <iostream>
8
9 template <typename InputIterator, typename Distance>
10 void advance_impl(InputIterator& i, Distance n, std::input_iterator_tag) {
11     std::cout << "InputIterator used" << std::endl; 
12     while (n--) ++i;
13 }
14
15 template <typename BidirectionalIterator, typename Distance>
16 void advance_impl(BidirectionalIterator& i, Distance n, std::bidirectional_iterator_
17     std::cout << "BidirectionalIterator used" << std::endl;
18     if (n >= 0) 
19         while (n--) ++i;
20     else 
21         while (n++) --i;
22 }
23
24 template <typename RandomAccessIterator, typename Distance>
25 void advance_impl(RandomAccessIterator& i, Distance n, std::random_access_iterator_t
26     std::cout << "RandomAccessIterator used" << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/JERJp9zLLlo 1/3
3/20/22, 6:47 PM - Example - Generic Programming Templates in C++

27     i += n;
28 }
29
30 template <typename InputIterator, typename Distance>
31 void advance_(InputIterator& i, Distance n) {
32     typename std::iterator_traits<InputIterator>::iterator_category category;    
33     advance_impl(i, n, category);                                                
34 }
35   
36 int main(){
37     
38 }
39

(/learn)

Succeeded

Explanation#
The expression std::iterator_traits::iterator_category category in line 32
determines the iterator category at compile-time. Based on the iterator
category, the most specific variant of the function template advance_impl(i,
n, category) is used in line 33. Each container returns an iterator of the
iterator category which corresponds to its structure.

In the next lesson, we’ll solve an exercise for tag dispatching in idioms and
patterns.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
// /
https://www.educative.io/courses/generic-templates-in-cpp/JERJp9zLLlo / 2/3
3/20/22, 6:47 PM - Example - Generic Programming Templates in C++

(https://join.hired.com/educative/?

utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Idioms and Patterns: Tag Dispatching - Exercise

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/JERJp9zLLlo 3/3
3/20/22, 6:48 PM - Exercise - Generic Programming Templates in C++

- Exercise
Let's solve the exercise on tag dispatching in this lesson.

We'll cover the following

• Problem Statement

Problem Statement#
Extend the example
(https://www.educative.io/collection/page/10370001/5799373671759872/6489
223903313920) template for Tag Dispatching given below. The following
program shows a typical example of tag dispatching on iterators. Call the
advance_ algorithm in the main function with different containers such as
std:.vector , std::list , and ::forward_list to put the iterator 5 positions
further.

1 // TemplatesTagDispatching.cpp
2
3 #include <iterator>
4 #include <forward_list>
5 #include <list>
6 #include <vector>
7 #include <iostream>
8
9 template <typename InputIterator, typename Distance>
10 void advance_impl(InputIterator& i, Distance n, std::input_iterator_tag) {
11     std::cout << "InputIterator used" << std::endl; 
12     while (n--) ++i;
13 }
14
15 template <typename BidirectionalIterator, typename Distance>
16 id d i l(Bidi ti lIt
https://www.educative.io/courses/generic-templates-in-cpp/qVjxlNmKJkp
t & i Di t td bidi ti l it t 1/3
3/20/22, 6:48 PM - Exercise - Generic Programming Templates in C++
16 void advance_impl(BidirectionalIterator& i, Distance n, std::bidirectional_iterator_
17     std::cout << "BidirectionalIterator used" << std::endl;
18     if (n >= 0) 
19         while (n--) ++i;
20     else 
21         while (n++) --i;
22 }
23
24 template <typename RandomAccessIterator, typename Distance>
25 void advance_impl(RandomAccessIterator& i, Distance n, std::random_access_iterator_t
(/learn)
26     std::cout << "RandomAccessIterator used" << std::endl;
27     i += n;
28 }
29
30 template <typename InputIterator, typename Distance>
31 void advance_(InputIterator& i, Distance n) {
32     typename std::iterator_traits<InputIterator>::iterator_category category;    
33     advance_impl(i, n, category);                                                
34 }
35   
36 int main(){
37     // call the above functions to move them 5 position further
38 }
39

In the next lesson, we’ll look at the solution to this exercise.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

https://www.educative.io/courses/generic-templates-in-cpp/qVjxlNmKJkp 2/3
3/20/22, 6:48 PM - Exercise - Generic Programming Templates in C++

Back Next

- Example - Solution

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qVjxlNmKJkp 3/3
3/20/22, 6:48 PM - Solution - Generic Programming Templates in C++

- Solution
Let's have a look at the solution to the last exercise in this lesson.

We'll cover the following

• Solution Review

• Explanation
• Performance

Solution Review#
1 // templatesTagDispatchingImplementation.cpp
2
3 #include <iterator>
4 #include <forward_list>
5 #include <list>
6 #include <vector>
7 #include <iostream>
8
9 template <typename InputIterator, typename Distance>
10 void advance_impl(InputIterator& i, Distance n, std::input_iterator_tag) {
11     std::cout << "InputIterator used" << std::endl; 
12     while (n--) ++i;
13 }
14
15 template <typename BidirectionalIterator, typename Distance>
16 void advance_impl(BidirectionalIterator& i, Distance n, std::bidirectional_iterator_
17     std::cout << "BidirectionalIterator used" << std::endl;
18     if (n >= 0) 
19         while (n--) ++i;
20     else 
21         while (n++) --i;
22 }
23
24 template <typename RandomAccessIterator, typename Distance>
(
https://www.educative.io/courses/generic-templates-in-cpp/qZzDY8XBMPk 1/4
3/20/22, 6:48 PM - Solution - Generic Programming Templates in C++
25 void advance_impl(RandomAccessIterator& i, Distance n, std::random_access_iterator_t
26     std::cout << "RandomAccessIterator used" << std::endl;
27     i += n;
28 }
29
30 template <typename InputIterator, typename Distance>
31 void advance_(InputIterator& i, Distance n) {
32     typename std::iterator_traits<InputIterator>::iterator_category category;    
33     advance_impl(i, n, category);                                               
34 }
35   
36 int main(){
37     
38     std::cout << std::endl;
39     
40     std::vector<int> myVec{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
41     auto myVecIt = myVec.begin();                                               
42     std::cout << "*myVecIt: " << *myVecIt << std::endl;
43     advance_(myVecIt, 5);
44     std::cout << "*myVecIt: " << *myVecIt << std::endl;
45     
46     std::cout << std::endl;
47     
48     std::list<int> myList{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
49     auto myListIt = myList.begin();                                             
50     std::cout << "*myListIt: " << *myListIt << std::endl;
51     advance_(myListIt, 5);
52     std::cout << "*myListIt: " << *myListIt << std::endl;
53     
54     std::cout << std::endl;
55     
56     std::forward_list<int> myForwardList{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
57     auto myForwardListIt = myForwardList.begin();                               
58     std::cout << "*myForwardListIt: " << *myForwardListIt << std::endl;
59     advance_(myForwardListIt, 5);
60     std::cout << "*myForwardListIt: " << *myForwardListIt << std::endl;
61     
62     std::cout << std::endl;
63     
64 }
65

Output 1.56s

https://www.educative.io/courses/generic-templates-in-cpp/qZzDY8XBMPk 2/4
3/20/22, 6:48 PM - Solution - Generic Programming Templates in C++

*myVecIt: 0

RandomAccessIterator used

*myVecIt: 5

*myListIt: 0

BidirectionalIterator used

*myListIt: 5

Explanation#
(/learn)

The expression std::iterator_traits::iterator_category category in line 32


determines the iterator category at compile-time. Based on the iterator
category, the most specific variant of the function template advance_impl(i,
n, category) is used in line 33. Each container returns an iterator of the
iterator category which corresponds to its structure. Therefore, line 41 gives
a random-access iterator, line 49 gives a bidirectional iterator, and line 57
gives a forward iterator, which is also an input iterator.

Performance#
From the performance point of view, this distinction makes a lot of sense
because a random-access iterator can be more quickly incremented than a
bidirectional iterator, and a bidirectional iterator can be more quickly
incremented than an input iterator. From the users perspective, we invoked
std::advance(it, 5) in lines 43, 51, and 59 to get the fastest version of the
function template which our container satisfies.

Let’s move on to type erasure idioms and patterns in the next lesson.

https://www.educative.io/courses/generic-templates-in-cpp/qZzDY8XBMPk 3/4
3/20/22, 6:48 PM - Solution - Generic Programming Templates in C++

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise Idioms and Patterns: Type Erasure

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qZzDY8XBMPk 4/4
3/20/22, 6:49 PM Idioms and Patterns: Type Erasure - Generic Programming Templates in C++

Idioms and Patterns: Type Erasure


In this lesson, we'll learn about type erasure in detail.

We'll cover the following

• Type Erasure

• Typical Use Case


• Case 1: Void Pointers

• Case 2: Object-Orientation
• Case 3: std::function

Type Erasure#
Type Erasure enables you to use various concrete types through a single
generic interface.

Type erasure is duck typing applied in C++

“When I see a bird that walks like a duck and swims like
a duck and quacks
like a duck, I call that bird a duck.” (James Whitcomb Rileys
(https://en.wikipedia.org/wiki/James_Whitcomb_Riley))

Of course, you’ve already used type erasure in C++ or C. The C-ish way of
type erasure is a void pointer; the C++ish way of type erasure is object-
orientation.

https://www.educative.io/courses/generic-templates-in-cpp/gk3xZy0yOYD 1/5
3/20/22, 6:49 PM Idioms and Patterns: Type Erasure - Generic Programming Templates in C++

Typical Use Case#


Type erasure can be performed with void pointers, object-orientation, or
templates.

Case 1: Void Pointers#


void qsort(void *ptr, std::size_t count, std::size_t size, cmp);

Before the qsort() , consider using:

int cmp(const void *a, const void *b);

The comparison function cmp should return a

negative integer: the first argument is less than the second

zero: both arguments are equal

positive integer: the first argument is greater than the second

Thanks to the void pointer, std::qsort is generally applicable but also quite
error-prone.

Maybe you want to sort a std::vector<int> , but you used a comparator for
C-strings. The compiler cannot catch this error because the type of
information was removed and we end up with undefined behavior.

In C++ we can do better.

Case 2: Object-Orientation#
Having a class hierarchy and using the BaseClass pointer instead of concrete
types is one way to enable type erasure

std::vector<const BaseClass*> vec;

https://www.educative.io/courses/generic-templates-in-cpp/gk3xZy0yOYD 2/5
3/20/22, 6:49 PM Idioms and Patterns: Type Erasure - Generic Programming Templates in C++

The vec object has a pointer to a constant BaseClasses .

Case 3: std::function #
std::function as a polymorphic function wrapper is a nice example of type
erasure in C++ . std::function can accept everything, which behaves like a
function. To be more precise, this can be any callable such as a function, a
function object, a function object created by std::bind , or just a lambda
function.

Let’s have a look at the difference between the three types listed above in the
following table:

Each Type-safe Easy to Common


Technique
Datatype Interface implment Base Class

void* Yes No Yes No

Object-
Orientatio No Yes Yes Yes
n

(/learn)
Templates Yes Yes No No

1 class Object {
2   public:
3   ...
4   struct Concept {
5     virtual ~Concept() {} 
6   };
7
8   template< typename T > 
9   struct Model : Concept {
10     ... 
11 };
https://www.educative.io/courses/generic-templates-in-cpp/gk3xZy0yOYD 3/5
3/20/22, 6:49 PM Idioms and Patterns: Type Erasure - Generic Programming Templates in C++
11   };
12
13   std::shared_ptr<const Concept> object; 
14 };

The small code snippet shows the structure of type erasure with templates.

The components are:

Object : Wrapper for a concrete type

object : Pointer to the concept

Concept : Generic interface

Model : Concrete class

Don’t be irritated by the names Object , object , Concept , and Model . They
are typically used for type erasure in the literature, so we stick to them. We
will see a more explained version of this in the example in the next lesson.

In the next lesson, we’ll look at a couple of examples of type erasure.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solution - Examples

https://www.educative.io/courses/generic-templates-in-cpp/gk3xZy0yOYD 4/5
3/20/22, 6:49 PM Idioms and Patterns: Type Erasure - Generic Programming Templates in C++
Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/gk3xZy0yOYD 5/5
3/20/22, 6:50 PM - Examples - Generic Programming Templates in C++

- Examples
In this lesson, we'll look at a couple of examples of type erasure.

We'll cover the following

• Example 1: Type Erasure Using Object-Oriented Programming

• Explanation
• Pros:

• Cons:
• Example 2: Type Erasure with Templates

• Explanation

Example 1: Type Erasure Using


Object-Oriented Programming#
1 // typeErasureOO.cpp
2
3 #include <iostream>
4 #include <string>
5 #include <vector>
6
7 struct BaseClass{
8     virtual std::string getName() const = 0;
9 };
10
11 struct Bar: BaseClass{
12     std::string getName() const override {
13         return "Bar";
14     }
15 };
16
https://www.educative.io/courses/generic-templates-in-cpp/mEZB4qG1Ox9 1/6
3/20/22, 6:50 PM - Examples - Generic Programming Templates in C++
16
17 struct Foo: BaseClass{
18     std::string getName() const override{
19         return "Foo";
20     }
21 };
22
23 void printName(std::vector<BaseClass*> vec){
24     for (auto v: vec) std::cout << v->getName() << std::endl;
25 }
26
27
28 int main(){
29     
30     std::cout << std::endl;
31     
32     Foo foo;
33     Bar bar; 
34     
35     std::vector<BaseClass*> vec{&foo, &bar};
36     
37     printName(vec);
38     
39     std::cout << std::endl;
40 }

Output 3.67s

Foo

Bar

Explanation#
The key point is that you can use instances of Foo or Bar instead of an
instance for BaseClass . std::vector<BaseClass*> (line 35) has a pointer to
BaseClass . Well, actually it has two pointers to BaseClass (derived) objects
https://www.educative.io/courses/generic-templates-in-cpp/mEZB4qG1Ox9 2/6
3/20/22, 6:50 PM - Examples - Generic Programming Templates in C++
BaseClass . Well, actually it has two pointers to BaseClass (derived) objects

and it is a vector of such pointers.


BaseClass is an abstract base class, which
is used in line 23. Foo and Bar (lines 11 and 17) are the concrete classes.

What are the pros and cons of this implementation with object-orientation?

Pros:#
Type-safe
Easy to implement

Cons:#
Virtual dispatch

Intrusive because the derived class must know about its base class

Example 2: Type Erasure with


Templates#
1 // TypeErasure.cpp
2
3 #include <iostream>
4 #include <memory>
5 #include <string>
6 #include <vector>
7
8 class Object {
9     
10 public:
11     template <typename T> 
12     explicit Object(T&& obj): object(std::make_shared<Model<T>>(std::forward<T>(obj)
13       
14     std::string getName() const { 
15         return object->getName(); 
16     }
17     
18    struct Concept {
19        virtual ~Concept() {}
20        virtual std::string getName() const = 0;
21 };
https://www.educative.io/courses/generic-templates-in-cpp/mEZB4qG1Ox9 3/6
3/20/22, 6:50 PM - Examples - Generic Programming Templates in C++
21    };
22
23    template< typename T > 
24    struct Model : Concept {
25        explicit Model(const T& t) : object(t) {}
26        std::string getName() const override {
27            return object.getName();
28        }
29      private:
30        T object;
31    };
32
33    std::shared_ptr<const Concept> object;
34 };
35
36
37 void printName(std::vector<Object> vec){
38     for (auto v: vec) std::cout << v.getName() << std::endl;
39 }
40
41 struct Bar{
42     std::string getName() const {
43         return "Bar";
44     }
45 };
46
47 struct Foo{
48     std::string getName() const {
49         return "Foo";
50     }
51 };
52
53 int main(){
54     
55     std::cout << std::endl;
56     
57     std::vector<Object> vec{Object(Foo()), Object(Bar())};
58     
59     printName(vec);
60     
61     std::cout << std::endl;
62 }

Output 1.64s
https://www.educative.io/courses/generic-templates-in-cpp/mEZB4qG1Ox9 4/6
3/20/22, 6:50 PM - Examples - Generic Programming Templates in C++
Output 1.64s

Foo

(/learn)
Bar

Explanation#
First of all, the std::vector uses instances (line 57) of type Object and not
pointers like in the previous object-oriented example. These instances can be
created with arbitrary types because it has a generic constructor (line 12).
The Object has the getName method (line 14) which is directly forwarded to
the getName of the object. object is of type std::shared_ptr<const Concept> .
The emphasis should not lay on the empty but on the virtual destructor in
line 19. When the std::shared_ptr<const Concept> goes out of scope, the
destructor is called. The static type of object is std::shared_ptr<const
Concept> but the dynamic type std::shared_ptr<Model<T>> . The virtual
destructor guarantees that the correct destructor is called. This means, in
particular, the destructor of the dynamic type. The getName method of
Concept is pure virtual (line 18), therefore, due to virtual dispatch, the
getName method of Model (line 24) is used. In the end, the getName methods
of Bar and Foo (lines 42 and 48) are applied in the printName function (line
37).

In the next lesson, we’ll solve an exercise on type erasure.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022
https://www.educative.io/courses/generic-templates-in-cpp/mEZB4qG1Ox9 5/6
utm_source educative&utm_medium
3/20/22, 6:50 PM
partner&utm_campaign March_2022
- Examples - Generic Programming Templates in C++

Back Next

Idioms and Patterns: Type Erasure - Exercise

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/mEZB4qG1Ox9 6/6
3/20/22, 6:51 PM - Exercise - Generic Programming Templates in C++

- Exercise
In this lesson, we'll solve an exercise on type erasure.

We'll cover the following

• Problem Statement

Problem Statement#
Compare the implementations of type erasure:

Implement a type deduction system with the help of type erasure which
returns a string representation corresponding to each data type. You need to
write the function for int , long long , char , void , and float .

1 #include <iostream>
2 #include <iostream>
3 #include <memory>
4 #include <string>
5 #include <typeinfo>
6 #include <vector>
7
8 // Implement the object struct
9
10 int main() {
11   // uncomment these lines after implementing object struct
12
13   /*
(/learn)
14   printType(Object::Model<int>{});
15   printType(Object::Model<double>{});
16   printType(Object::Model<void>{});
17   printType(Object::Model<Test>{});
18   printType(Object::Model<Object>{});
19   printType(Object::Model<long long>{});
(
https://www.educative.io/courses/generic-templates-in-cpp/q2W30m1wg1D {}) 1/2
3/20/22, 6:51 PM - Exercise - Generic Programming Templates in C++
20   printType(Object::Model<std::string>{});
21   printType(Object::Model<std::vector<int>>{});  
22   */
23 }

In the next lesson, we’ll look at the solution to this exercise.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Examples - Solution

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/q2W30m1wg1D 2/2
3/20/22, 6:51 PM - Solution - Generic Programming Templates in C++

- Solution
Let's have a look at the solution of the last exercise.

We'll cover the following

• Solution Review

• Explanation

Solution Review#
1 // TypeErasureTypeInfo.cpp
2
3 #include <iostream>
4 #include <memory>
5 #include <string>
6 #include <typeinfo>
7 #include <vector>
8
9 struct Object{
10    std::string getTypeName() const { return _inner->getTypeName(); }
11    struct Concept{
12       using ptr = std::unique_ptr<Concept>;
13       virtual std::string getTypeName() const = 0;
14    };
15    template <typename T> 
16    struct Model : Concept{
17       std::string getTypeName() const override { return typeid(T).name(); }
18    };
19 private:
20    typename Concept::ptr _inner;
21 };
22
23 template <>
24 struct Object::Model<long long> : Object::Concept{
25    std::string getTypeName() const override { return "long long";}
26 };
https://www.educative.io/courses/generic-templates-in-cpp/qVpxBkEAVL2 1/4
3/20/22, 6:51 PM - Solution - Generic Programming Templates in C++
27
28 template <>
29 struct Object::Model<std::string> : Object::Concept{
30    std::string getTypeName() const override { return "std::string<char>";}
31 };
32
33 template <>
34 struct Object::Model<std::vector<int>> : Object::Concept{
35    std::string getTypeName() const override { return "std::vector<int>";}
36 };
37    
38
39 template <typename T>
40 void printType(T&& t){
41    std::cout << t.getTypeName() << std::endl;
42 }
43
44 class Test{};
45
46 int main(){
47    
48    printType(Object::Model<int>{});
49    printType(Object::Model<double>{});
50    printType(Object::Model<void>{});
51    printType(Object::Model<Test>{});
52    printType(Object::Model<Object>{});
53    printType(Object::Model<long long>{});
54    printType(Object::Model<std::string>{});
55    printType(Object::Model<std::vector<int>>{});   
56     
57 }

Output 1.4s

d
(/learn)
v

4Test

6Object

long long

std::string<char>

std::vector<int>

https://www.educative.io/courses/generic-templates-in-cpp/qVpxBkEAVL2 2/4
3/20/22, 6:51 PM - Solution - Generic Programming Templates in C++

Explanation#
The function template printType returns a string representation for each
type. In the general case, the primary template Model (lines 15 – 18) is used.
The implementation uses the typeid operator to get the name. Full
specializations are also available for the types long long (lines 23 – 26),
std::string (lines 28 – 31), and int (lines 33 – 36). The full specializations
provide personalized string representations.

In this chapter, we have learned about design techniques of C++ templates.


In the next chapter, we’ll look at the future concepts in C++20.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Exercise Overview

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qVpxBkEAVL2 3/4
3/20/22, 6:51 PM - Solution - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/qVpxBkEAVL2 4/4
3/20/22, 6:52 PM Overview - Generic Programming Templates in C++

Overview
In this lesson, we'll look at an overview of what concepts are needed in C++20.

We'll cover the following

• Too Specific Versus Too Generic

• Too Specific
• Narrowing Conversion

• Integral Promotion
• Too Generic

• Concepts to Our Rescue

• Advantages

Until C++20, we have two diametral ways to think about functions or user-
defined types (classes). Functions or classes can be defined on specific types
or on generic types. In the second case, we call them to function or class
templates.

There exist two extremes while talking about functions in C++. Let’s take a
closer look at two function implementations:

Too Specific Versus Too Generic#

Too Specific Too Generic


https://www.educative.io/courses/generic-templates-in-cpp/xoLVB57lMrq 1/8
3/20/22, 6:52 PM Overview - Generic Programming Templates in C++

#include <iostream>
#include <iostream>

void needInt(int i){ // 1
template<typenameT>

  std::cout<< i << std::endl;
T gcd(T a, T b){

}
  if( b == 0 ){


    return a; 

int main(){
  }else{

  double d{1.234};
    return gcd(b, a % b);

  needInt(d);
  }

}
}


int main(){


  std::cout<< gcd(100, 10)  << st

d::endl;


  std::cout<< gcd(3.5, 4.0) << st

d::endl;

Too Specific#
It’s quite a job to define for each specific type a function or a class. To avoid
that burden, type conversion comes often to our rescue but it is also part of
the problem.

Narrowing Conversion#
We have a function needInt(int a) in line 3 which we can be invoked with a
double . Now narrowing conversion takes place.

1 #include <iostream>
2
3 void needInt(int i){ 
4   std::cout<< i << std::endl;
5 }
https://www.educative.io/courses/generic-templates-in-cpp/xoLVB57lMrq 2/8
3/20/22, 6:52 PM Overview - Generic Programming Templates in C++
5 }
6
7 int main(){
8   double d{1.234};
9   needInt(d);
10 }

Output 1.52s

We assume that this is not the behavior we wanted. We started with a


double and ended with an int .

But conversion also works the other way around.

Integral Promotion#
We have a user-defined type MyHouse . An instance of MyHouse can be
constructed in two ways. When invoked without any argument in line 5, its
attribute family is set to an empty string. This means the house is still empty.
To quickly check if the house is empty or full, we implemented a conversion
operator to bool in line 8.

1 #include <iostream>
2 #include <string>
3
4 struct MyHouse{
5     MyHouse() = default;                            
6     MyHouse(const std::string& fam): family(fam){}
7     
8     operator bool(){ return !family.empty(); }                             
9     
10 std::string family = "";
https://www.educative.io/courses/generic-templates-in-cpp/xoLVB57lMrq 3/8
3/20/22, 6:52 PM Overview - Generic Programming Templates in C++
10     std::string family =  ;
11 };
12
13 void needInt(int i){
14     std::cout << "int: " << i << std::endl;
15 }
16
17 int main(){
18     
19     std::cout << std::boolalpha << std::endl;
20     
21     MyHouse firstHouse;
22     if (!firstHouse){                                        
23         std::cout << "The firstHouse is still empty." << std::endl;
24     };
25     
26     MyHouse secondHouse("grimm");                               
27     if (secondHouse){
28         std::cout << "Family grimm lives in secondHouse." << std::endl;
29     }
30     
31     std::cout << std::endl;
32     
33     needInt(firstHouse);                             
34     needInt(secondHouse);            
35     
36     std::cout << std::endl;
37     
38 }

Output 2.46s

The firstHouse is still empty.

Family grimm lives in secondHouse.

int: 0

int: 1

https://www.educative.io/courses/generic-templates-in-cpp/xoLVB57lMrq 4/8
3/20/22, 6:52 PM Overview - Generic Programming Templates in C++

Now, instances of MyHouse can be used, when an int is required. Strange!

Because of the overloaded operator bool in line 8, instances of MyHouse can


be used as an int and can, therefore, be used in arithmetic expressions:
auto res = MyHouse() + 5 . This was not our intention! But we have noted it
just for completeness. With C++11, we should declare those conversion
operators as explicit. Therefore, implicit conversions will not take place.

Too Generic#
Generic functions or classes can be invoked with arbitrary values. If the
values do not satisfy the requirements of the function or class, it is not a
problem because you will get a compile-time error.

1 #include <iostream>
2
3 template<typename T>
4 T gcd(T a, T b){
5   if( b == 0 ){ return a; }
6   else{
7     return gcd(b, a % b);
8   }
9 }
10
11 int main(){
12
13   std::cout << std::endl;
14
15   std::cout << gcd(100, 10)  << std::endl;
16  
17   std::cout << gcd(3.5, 4.0)<< std::endl;
18   std::cout << gcd("100", "10") << std::endl;
19
20   std::cout << std::endl;
21
22 }

https://www.educative.io/courses/generic-templates-in-cpp/xoLVB57lMrq 5/8
3/20/22, 6:52 PM Overview - Generic Programming Templates in C++

Output 1.97s

main.cpp: In instantiation of 'T gcd(T, T) [with T = double]':

main.cpp:17:28: required from here

main.cpp:7:21: error: invalid operands of types 'double' and 'double' to


binary 'operator%'

7 | return gcd(b, a % b);


| ~~^~~

main.cpp: In instantiation of 'T gcd(T, T) [with T = const char*]':

main.cpp:18:31: required from here

main.cpp:7:21: error: invalid operands of types 'const char*' and 'const


char*' to binary 'operator%'

What is the problem with this error message?

Of course, it is quite long and quite difficult to understand but our crucial
concern is a different one. The compilation fails because neither double nor
the C-string supports the % operator. This means the error is due to the
failed template instantiation for double and C-string. This is too late and,
therefore, really bad. No template instantiation for type double or C-strings
(/learn)
should even be possible. The requirements for the arguments should be part
of the function declaration and not a side-effect of an erroneous template
instantiation.

Now concepts come to our rescue.

Concepts to Our Rescue#


With concepts, we get something in between. We can define functions or
classes which act on semantic categories. Meaning, the arguments of
functions or classes are neither too specific nor too generic but named sets
https://www.educative.io/courses/generic-templates-in-cpp/xoLVB57lMrq 6/8
3/20/22, 6:52 PM Overview - Generic Programming Templates in C++

of requirements such as Integral .

Advantages#
Express the template parameter requirements as part of the interface

Support the overloading of functions and the specialization of class


templates

Generate drastically improved error messages by comparing the


requirements of the template parameter with the template arguments

Use them as placeholders for generic programming

Empowers you to define your concepts

Can be used for all kinds of templates

In the next lesson, we’ll learn about the history of C++ and talk about future
concepts.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

- Solution History

Mark as Completed
https://www.educative.io/courses/generic-templates-in-cpp/xoLVB57lMrq 7/8
3/20/22, 6:52 PM Overview - Generic Programming Templates in C++

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/xoLVB57lMrq 8/8
3/20/22, 6:53 PM History - Generic Programming Templates in C++

History
In this lesson, we'll learn about the history of C++ and talk about future concepts.

We'll cover the following

• The Inspiration from Haskell

• Classical Concepts
• Concepts

• The Advantages of Concepts

The Inspiration from Haskell#


Type classes are interfaces for similar types. If a type is a member of a type
class, it has to have specific properties. Type classes play a similar role in
generic programming as interfaces play in object-oriented programming.
Here you can see a part of Haskell’s type classes hierarchy.

https://www.educative.io/courses/generic-templates-in-cpp/7DA9qmDpQZB 1/4
3/20/22, 6:53 PM History - Generic Programming Templates in C++

Haskell Type Class Hierarchy

Haskell’s type classes build a hierarchy. The type class Ord is a subclass of
the type class Eq . Therefore, instances of the type class Ord have to be
members of the type class Eq and in addition support the comparison
operators.

Classical Concepts#
The key idea of generic programming with templates is, to define functions
and classes that can be used with different types. But it will often happen
that you instantiate a template with the wrong type. The result may be a
cryptic error message that is many pages long It is sad but true: templates in
https://www.educative.io/courses/generic-templates-in-cpp/7DA9qmDpQZB 2/4
3/20/22, 6:53 PM History - Generic Programming Templates in C++
cryptic error message that is many pages long. It is sad but true: templates in
C++ are known for this. Therefore, classical concepts were planned as one of

the great features of C++11. They should allow you to specify constraints for
templates that can be verified by the compiler. Due to their complexity, they
were removed in July 2009 from the standard: “The C++0x concept design
evolved into a monster of complexity.” (Bjarne Stroustrup)

Concepts#
With C++20, we will get concepts. Although concepts are in the first
implementations simplified classical concepts, they have a lot to offer.

The Advantages of Concepts#


(/learn)

Concepts

Empower the programmer to express their requirements as part of the


interface directly.
Support the overloading of functions and the specialization of class
templates based on the requirements of the template parameters.

Produce drastically improved error messages by comparing the


requirements of the template parameter with the applied template
arguments.
Can be used as placeholders for generic programming.
Empower you to define your own concepts.

We will get the benefits without additional compile-time or runtime time


costs. Concepts are similar to Haskell’s type classes. Concepts describe
semantic categories and not syntactic restrictions. For types of the standard
library, we get library concepts
(https://en.cppreference.com/w/cpp/language/constraints) such as
DefaultConstructible , MoveConstructible , CopyConstructible ,
MoveAssignable , CopyAssignable , or Destructible . For the containers, we get
https://www.educative.io/courses/generic-templates-in-cpp/7DA9qmDpQZB 3/4
3/20/22, 6:53 PM History - Generic Programming Templates in C++
MoveAssignable , CopyAssignable , or Destructible . For the containers, we get
concepts such as ReversibleContainer , AllocatorAwareContainer ,

SequenceContainer , ContiguousContainer , AssociativeContainer , or


UnorderedAssociativeContainer . You can read more about concepts and their
constraints here: cppreference.com
(https://en.cppreference.com/w/cpp/named_req).

In the next lesson, we’ll learn about the details of functions and classes with
reference to concepts.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Overview Functions and Classes

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/7DA9qmDpQZB 4/4
3/20/22, 6:54 PM Functions and Classes - Generic Programming Templates in C++

Functions and Classes


Let's learn about coming C++ concepts in detail in this lesson.

We'll cover the following

• Functions

• Classes
• Methods of a Class

• More Requirements
• Overloading

• Specialization

Concepts are part of the template declaration.

Functions#
Using the concept Sortable .

Implicit The implicit version from the left is


syntactic sugar to the explicit

template<Sortable Cont>

version:
void sort(Cont& container){

...
Explicit
}

The container has to be Sortable .


https://www.educative.io/courses/generic-templates-in-cpp/RLP6yZOO1YK 1/5
3/20/22, 6:54 PM Functions and Classes - Generic Programming Templates in C++

template<typename Cont> 

   requires Sortable<Cont>()

void sort(Cont& container){

    ...

Sortable has to be a constant expression that is a predicate. That means that


the expression has to be evaluable at compile-time and has to return a
boolean.

If you invoke the sort algorithm with a container lst that is not sortable,
you will get a unique error message from the compiler.

Usage:

std::list<int> lst = {1998, 2014, 2003, 2011};

sort(lst); // ERROR: lst is no random-access container with <

You can use concepts for all kind of templates.

Classes#
We can define a class template MyVector that will only accept objects as
template arguments:

template<Object T>

class MyVector{};

MyVector<int> v1; // OK

MyVector<int&> v2 // ERROR: int& does not satisfy the constraint Object

Now the compiler complains that the reference (int&) is not an object
https://www.educative.io/courses/generic-templates-in-cpp/RLP6yZOO1YK 2/5
3/20/22, 6:54 PM Functions and Classes - Generic Programming Templates in C++
Now, the compiler complains that the reference (int&) is not an object.
MyVector can be further adjusted.

A reference is not an object.

Methods of a Class#
template<Object T>

class MyVector{

   ...

   requires Copyable<T>()

   void push_back(const T& e);

   ...

};

Now the method push_back from MyVector requires that the template
argument has to be copy-able. The concepts have to be placed before the
method declaration.

More Requirements#
A template can have more than one requirement for its template
parameters.

template <SequenceContainer S,

         EqualityComparable<value_type<S>> T>

Iterator_type<S> find(S&& seq, const T& val){ 

    ...

The function template find has two requirements. On one hand, the
container has to store its elements in a linear arrangement
( SequenceContainer ), on the other hand, the elements of the container have
to be equally comparable: EqualityComparable<value_type<S>> .

https://www.educative.io/courses/generic-templates-in-cpp/RLP6yZOO1YK 3/5
3/20/22, 6:54 PM Functions and Classes - Generic Programming Templates in C++

Overloading#
Concepts support the overloading of functions.

template<InputIterator I>

void advance(I& iter, int n){...}

template<BidirectionalIterator I>

void advance(I& iter, int n){...}

template<RandomAccessIterator I>
void advance(I& iter, int n){...}

std::list<int> lst{1,2,3,4,5,6,7,8,9}; 

std::list<int>:: iterator i = lst.begin();

std::advance(i, 2); // BidirectionalIterator

(/learn)
The function template std::advance puts its iterator n positions further.
Depending if the iterator is a forward, a bidirectional, or a random access
iterator, different function templates will be used. In case of a std::list , the
BidirectionalIterator will be chosen.

Concepts also support the specialization of class templates.

Specialization#
template<typename T>

class MyVector{};

template<Object T>

class MyVector{};

MyVector<int> v1; // Object T

MyVector<int&> v2; // typename T

For MyVector<int&> v2 , the compiler uses the general template in the first
line; on the contrary, the compiler uses for MyVector<int> the specialization
https://www.educative.io/courses/generic-templates-in-cpp/RLP6yZOO1YK 4/5
3/20/22, 6:54 PM Functions and Classes - Generic Programming Templates in C++

template<Object T> class MyVector{} .

MyVector<int&> goes to the unconstrained template parameter.

MyVector<int> goes to the constrained template parameter.

In the next lesson, we’ll study the placeholder syntax.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

History Placeholder Syntax

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/RLP6yZOO1YK 5/5
3/20/22, 6:54 PM Placeholder Syntax - Generic Programming Templates in C++

Placeholder Syntax
Let's learn about placeholder syntax in this lesson.

We'll cover the following

• Placeholder Syntax: auto

• Inconsistency in C++14
• Constrained and Unconstrained Placeholders

• Example:

With auto , C++11 has unconstrained placeholders. We can use concepts in


C++20 as constrained placeholders. Decisive quantum leap does not look so
thrilling at the first glimpse. C++ templates will become easy to use C++
features.

According to our definition, C++98 is not a consistent language. By


consistent, we mean that you have to apply a few rules to derived C++ syntax
from it. C++11 is something in between. For example, we have consistent
rules like initializing all with curly braces (see { } - Initialization
(https://www.modernescpp.com/index.php/initialization)). Of course, even
C++14 has a lot of features where we miss a consistent principle. One of the
favorites is the generalized lambda function.

Placeholder Syntax: auto #

https://www.educative.io/courses/generic-templates-in-cpp/gxvvA60vz4l 1/5
3/20/22, 6:54 PM Placeholder Syntax - Generic Programming Templates in C++

auto genLambdaFunction= [](auto a, auto b) { 

   return a < b;

};

template <typename T, typename T2>    // 3

auto genFunction(T a, T2 b){          // 4

   return a < b; 

Inconsistency in C++14#
By using the placeholder auto for the parameter a and b , the generalized
lambda function becomes - in a magic way - a function template. We know,
genLambdaFunction is a function object that has an overloaded call operator
which accepts two type parameters. The genFunction is also a function
template. But wouldn’t it be nice to define a function template by just using
auto in a function definition? This would be consistent but is not possible.
Hence, we have to use a lot more syntax (line 3 and 4). That syntax is often
too difficult for a lot of C++ programmer.

Exactly that inconsistency will be removed with the placeholder syntax.


Therefore, we have a new simple principle and C++ will become - according
to my definition - a lot easier to use.

Generic Lambdas introduced a new way to define templates.

Constrained and Unconstrained


Placeholders#
https://www.educative.io/courses/generic-templates-in-cpp/gxvvA60vz4l 2/5
3/20/22, 6:54 PM Placeholder Syntax - Generic Programming Templates in C++

We will get unconstrained and constrained placeholders. auto is an


unconstrained placeholder because a with auto defined variable can be of
any type. A concept is a constrained placeholder because it can only be used
to define a variable that satisfies the concept .

General Rule: Constrained Concepts can be used where unconstrained


templates ( auto ) are usable.

Let’s define and use a simple concept before we dig into the details.

Example:#
1 // conceptsPlaceholder.cpp
2
3 #include <iostream>
4 #include <type_traits>
5 #include <vector>
6
7 template<typename T>
8 concept bool Integral(){
9   return std::is_integral<T>::value;
10 }
11
12 Integral getIntegral(auto val){
13   return val;
14 }
15
16 int main(){
17   
18   std::cout << std::boolalpha << std::endl;
19   
20   std::vector<int> myVec{1, 2, 3, 4, 5};
21   for (Integral& i: myVec) std::cout << i << " ";
22   std::cout << std::endl;  
23
24   Integral b= true;
25   std::cout << b << std::endl;
26   
27   Integral integ= getIntegral(10);
28   std::cout << integ << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/gxvvA60vz4l 3/5
3/20/22, 6:54 PM Placeholder Syntax - Generic Programming Templates in C++
28   std::cout << integ << std::endl;
29 (/learn)
  
30   auto integ1= getIntegral(10);
31   std::cout << integ1 << std::endl;
32   
33   std::cout << std::endl;
34
35 }

Output 2.34s

1 2 3 4 5

true

10

10

We have defined in line 8 the concept Integral . The concept Integral will
evaluate to true if the predicate std::is_integral<T>::value returns true
for T . std::is_integral<T> is a function of the type-traits
(https://www.educative.io/collection/page/10370001/5799373671759872/6380
229176066048) library. The functions of the type-traits library enable,
amongst other things, that we can check types at compile-time. Hence, we
iterate over Integral 's in the range-based for-loop in line 21 and the
variable b in line 24 has to be Integral . Our usage of concepts goes on in
lines 27 and 30. We required in line 27 that the return type of getIntegral
(line 12) has to fulfill the concept Integral . We’re not so strict in line 30.
Here we’re fine with an unconstrained placeholder.

https://www.educative.io/courses/generic-templates-in-cpp/gxvvA60vz4l 4/5
3/20/22, 6:54 PM Placeholder Syntax - Generic Programming Templates in C++

In the next lesson, we’ll discuss the predefined concepts in C++20.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Functions and Classes Predefined Concepts

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/gxvvA60vz4l 5/5
3/20/22, 6:56 PM Predefined Concepts - Generic Programming Templates in C++

Predefined Concepts
Let's dive deep into predefined concepts of C++20 in this lesson.

We'll cover the following

• Predefined Concept

• Concepts Definition: Variable Concepts


• Concepts Definition: Function Concepts

• Concepts TS
• Concepts Draft

• The Concept Equal

Before moving on to predefined concepts, let’s get to know about Syntactic


Sugar.

Syntactic Sugar: This is from Wikipedia


(https://en.wikipedia.org/wiki/Syntactic_sugar): In computer science,
syntactic sugar is syntax within a programming language that is
designed to make things easier to read or to express. It makes the
language sweeter for human use: things can be expressed more clearly,
more concisely, or in an alternative style that some may prefer.

Predefined Concept#
We should use the predefined concepts. cppreference.com
(https://en cppreference com/w/cpp/named req) gives a great introduction to
https://www.educative.io/courses/generic-templates-in-cpp/YQEzLDAKWVM 1/7
3/20/22, 6:56 PM Predefined Concepts - Generic Programming Templates in C++
(https://en.cppreference.com/w/cpp/named_req) gives a great introduction to
predefined concepts. Here are a few of them:

Core language concepts Object concepts

Same Destructible
DerivedFrom Constructible
ConvertibleTo DefaultConstructible
Common MoveConstructible
Integral Copy Constructible

Signed Integral Movable


Unsigned Integral Copyable
Assignable Semi-regular
Swappable Regular

Comparison concepts Callable concepts

Boolean Callable
EqualityComparable RegularCallable

StrictTotallyOrdered Predicate
Relation

StrictWeakOrder

There are two ways to define concepts: variable concepts and function
concepts. If we use a variable template for our concept, it’s called a variable
concept; in the second case a function concept.

Concepts Definition: Variable


Concepts#

https://www.educative.io/courses/generic-templates-in-cpp/YQEzLDAKWVM 2/7
3/20/22, 6:56 PM Predefined Concepts - Generic Programming Templates in C++

template<typename T>

concept bool Integral =

    std::is_integral<T>::value;

We have defined the concept Integral by using a variable template.


Variable templates are new with C++14 and declare a family of variables.
The concept Integral will evaluate to true if the predicate
std::is_integral<T>::value returns true for T . std::is_integral<T> is a
function of the type-traits
(https://www.educative.io/collection/page/10370001/5799373671759872/6380
229176066048) library. The functions of the type-traits library enable,
amongst other things, that we can check types at compile time.

Concepts Definition: Function


Concepts#
The original syntax of Concepts Technical Specification (Concepts TS) was a
bit adjusted to the proposed Draft C++20 Standard. Here is the original
syntax from the Concepts TS, which is used in this course.

Concepts TS#
template<typename T>

concept bool Equal(){

  return requires(T a, T b) {

    { a == b } -> bool;

    { a != b } -> bool;

  }; 

Integral is a variable concept and Equal is a function concept Both return


https://www.educative.io/courses/generic-templates-in-cpp/YQEzLDAKWVM 3/7
3/20/22, 6:56 PM Predefined Concepts - Generic Programming Templates in C++
Integral is a variable concept and Equal is a function concept. Both return
a boolean.

The type parameter T fulfills the variable concept Integral if


std::is_integral<T>::value returns true.

The type parameter T fulfills the function concept Equal if there are
overloaded operators == and != for T that returns a boolean.

Concepts Draft#
The proposed syntax for C++20 is even more concise.

template<typename T>

concept Equal =

  requires(T a, T b) {

    { a == b } -> bool;

    { a != b } -> bool;

};

T fulfills the function concept if == and != are overloaded and return


a boolean.

The Concept Equal#


1 // conceptsDefintionEqual.cpp
2
3 #include <iostream>
4
5 template<typename T>
6 concept bool Equal(){
7   return requires(T a, T b) {
8     { a == b } -> bool;
9     { a != b } -> bool;
10   };
11 }
12
13 bool areEqual(Equal a, Equal b){
14   return a == b;
15 }
16
17
{
https://www.educative.io/courses/generic-templates-in-cpp/YQEzLDAKWVM 4/7
3/20/22, 6:56 PM Predefined Concepts - Generic Programming Templates in C++
18 struct WithoutEqual{
19   bool operator==(const WithoutEqual& other) = delete;
20 };
21
22 struct WithoutUnequal{
23   bool operator!=(const WithoutUnequal& other) = delete;
24 };
25
26
27
28 int main(){
29   
30   std::cout << std::boolalpha << std::endl;
31   
32   std::cout << "areEqual(1, 5): " << areEqual(1, 5) << std::endl;
33   
34   bool res = areEqual(WithoutEqual(),  WithoutEqual());
35   
36   bool res2 = areEqual(WithoutUnequal(),  WithoutUnequal());
37   
38   std::cout << std::endl;
39   
40 }
41

(/learn)

Output 2.01s

We used the concept Equal in the (generic) function areEqual (line 13 to 15)
and that’s not so exciting.

What’s more interesting is if we use the class WithoutEqual and


WithoutUnequal . We set for both the == or respectively the != operator to
delete . The compiler complains immediately that both types do not fulfill
the concept
https://www.educative.io/courses/generic-templates-in-cpp/YQEzLDAKWVM 5/7
3/20/22, 6:56 PM Predefined Concepts - Generic Programming Templates in C++
the concept.

Let’s have a look at the screenshot of the error taken from the machine:

In the next lesson, we will study the predefined concepts Equal and Ord in
detail.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Placeholder Syntax Define your Concepts: Equal and Ord

Mark as Completed

https://www.educative.io/courses/generic-templates-in-cpp/YQEzLDAKWVM 6/7
3/20/22, 6:56 PM Predefined Concepts - Generic Programming Templates in C++

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/YQEzLDAKWVM 7/7
3/20/22, 6:57 PM Define your Concepts: Equal and Ord - Generic Programming Templates in C++

Define your Concepts: Equal and Ord


In this lesson, we'll define the concepts Equal and Ord for C++.

We'll cover the following

• Eq versus Equal

• Haskell’s Type Class Ord


• The Concept Equal and the Concept Ord

Eq versus Equal #

The Type Class Eq The Concept Equal


(Haskell) (C++)
class Eq a where
template <typename T>

  (==) :: a -> a -> Bool
concept bool Equal(){

  (/=) :: a -> a -> Bool
  return requires(T a, T b){


    { a == b } -> bool;


    { a != b } -> bool;


  };

(/learn)
Let’s have a closer look at Haskell’s type class Eq . Eq requires from its
instances, that

they have equal == and unequal /= operation that returns a Bool.


https://www.educative.io/courses/generic-templates-in-cpp/qVZG1wrXBp3 1/7
3/20/22, 6:57 PM Define your Concepts: Equal and Ord - Generic Programming Templates in C++

both take two arguments ( a -> a ) of the same type.

If you compare Haskell’s type class with C++'s concept, you see the similarity.

Of course, the instances are the concrete types such as int .

Haskell Type Class

Now we have two questions in mind if we look at Haskell’s type hierarchy


above. How is the definition of the type class Ord in Haskell and can we
model the inheritance relation in C++?

Haskell’s Type Class Ord #


https://www.educative.io/courses/generic-templates-in-cpp/qVZG1wrXBp3 2/7
3/20/22, 6:57 PM Define your Concepts: Equal and Ord - Generic Programming Templates in C++

class Eq a => Ord a where

  compare :: a -> a -> Ordering 
  (<) :: a -> a -> Bool

  (<=) :: a -> a -> Bool

  (>) :: a -> a -> Bool

  (>=) :: a -> a -> Bool

  max :: a -> a -> a

Each type supporting Ord must support Eq .

The most interesting point about the typeclass Ord is the first line of its
definition. An instance of the typeclass Ord has to be already an instance of
the typeclass Eq . Ordering is an enumeration having the values EQ , LT , and
GT .

The Concept Equal and the Concept


Ord #
Let’s define the corresponding concepts in C++.

The concept Equal The Concept Ord

https://www.educative.io/courses/generic-templates-in-cpp/qVZG1wrXBp3 3/7
3/20/22, 6:57 PM Define your Concepts: Equal and Ord - Generic Programming Templates in C++

template<typename T> 
template <typename T> 

concept bool Equal(){
concept bool Ord(){

  return requires(T a, T b){
  return requires(T a, T b){

    { a == b } -> bool;
    requires Equal<T>();

    { a != b } -> bool;
      { a <= b } -> bool;

  };
      { a < b } -> bool;

}
      { a > b } -> bool;


      { a >= b } -> bool; 


  };

To make the job a little bit easier, we ignored the requirements compare and
max from Haskell’s type class in the concept Ord . The key point about the
concept is that the line requires Equal<T>() . Here we required that the type
parameter T has to fulfill the requirement Equal . If we use more
requirements such as in the definition of the concept Equal , each
requirement from top to bottom will be checked. That will be done in a
short-circuiting evaluation. So, the first requirement returning false will
end the process.

1 // conceptsDefintionOrd.cpp
2 #include <iostream>
3 #include <unordered_set>
4
5 template<typename T>
6 concept bool Equal(){
7   return requires(T a, T b){
8     { a == b } -> bool;
9     { a != b } -> bool;
10   };
11 }
12
13 template <typename T>
14 concept bool Ord(){
15   return requires(T a, T b){
16     requires Equal<T>();
17     { a <= b } -> bool;
18     { a < b } -> bool;
https://www.educative.io/courses/generic-templates-in-cpp/qVZG1wrXBp3 4/7
3/20/22, 6:57 PM Define your Concepts: Equal and Ord - Generic Programming Templates in C++

19     { a > b } -> bool;
20     { a >= b } -> bool;
21   };
22 }
23
24 bool areEqual(Equal a, Equal b){
25   return a == b;
26 }
27
28 Ord getSmaller(Ord a, Ord b){
29   return (a < b) ? a : b;
30 }
31     
32 int main(){
33   
34   std::cout << std::boolalpha << std::endl;
35   
36   std::cout << "areEqual(1, 5): " << areEqual(1, 5) << std::endl;
37   
38   std::cout << "getSmaller(1, 5): " << getSmaller(1, 5) << std::endl;
39   
40   std::unordered_set<int> firSet{1, 2, 3, 4, 5};
41   std::unordered_set<int> secSet{5, 4, 3, 2, 1};
42   
43   std::cout << "areEqual(firSet, secSet): " << areEqual(firSet, secSet) << std::endl
44   
45   auto smallerSet= getSmaller(firSet, secSet);
46
47   std::cout << std::endl;
48   
49 }

Output 1.76s

main.cpp: In function 'int main()':

main.cpp:45:45: error: cannot call function 'auto getSmaller(auto:2, auto:2)


[with auto:2 = std::unordered_set<int>]'

45 | auto smallerSet= getSmaller(firSet, secSet);

| ^

main.cpp:28:5: note: constraints not satisfied

28 | Ord getSmaller(Ord a, Ord b){

| ^~~~~~~~~~

main.cpp:14:14: note: within 'template<class T> concept bool Ord() [with T =


std::unordered_set<int>]'

https://www.educative.io/courses/generic-templates-in-cpp/qVZG1wrXBp3 5/7
3/20/22, 6:57 PM Define your Concepts: Equal and Ord - Generic Programming Templates in C++
_ ]
14 | concept bool Ord(){

| ^~~

main.cpp:14:14: note: with 'std::unordered_set<int> a'

main.cpp:14:14: note: with 'std::unordered_set<int> b'

main.cpp:14:14: note: the required expression '(a <= b)' would be ill-formed

main.cpp:14:14: note: the required expression '(a < b)' would be ill-formed

main.cpp:14:14: note: the required expression '(a > b)' would be ill-formed

main.cpp:14:14: note: the required expression '(a >= b)' would be ill-formed

Equality and inequality are defined for the data types int and
std::unordered_set .

What would happen, when we uncomment line 45 and compare firSet and
secSet . To remind you, the type of both variables is std::unordered_set .
This says very explicitly that they don’t support an ordering.

Let’s check what happens when we run this code:

Of course, the compilation would fail.

In the next lesson, we’ll discuss other predefined concepts: Regular and
SemiRegular.

https://www.educative.io/courses/generic-templates-in-cpp/qVZG1wrXBp3 6/7
3/20/22, 6:57 PM Define your Concepts: Equal and Ord - Generic Programming Templates in C++

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Predefined Concepts Define your Concept: Regular and Se…

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/qVZG1wrXBp3 7/7
3/20/22, 6:58 PM Define your Concept: Regular and SemiRegular - Generic Programming Templates in C++

Define your Concept: Regular and


SemiRegular
In this lesson, we'll gain an understanding of the important predefined concepts: Regular
and SemiRegular.

We'll cover the following

• References are not Regular

The first question we have to answer is quite obvious. What is a Regular or a


SemiRegular type? Our answer is based on the proposal p0898
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0898r3.pdf). We
assume you may have already guessed it that Regular and SemiRegular are
concepts, which are defined by other concepts. Given is the list of all
concepts.

Regular SemiRegular
DefaultConstructible Regular without

CopyConstructible, EqualityComparable
CopyAssignable
MoveConstructible,
MoveAssignable
Destructible

Swappable
https://www.educative.io/courses/generic-templates-in-cpp/B8j9KY0g2ON 1/7
3/20/22, 6:58 PM Define your Concept: Regular and SemiRegular - Generic Programming Templates in C++

EqualityComparable

The term Regular goes back to the father of the Standard Template Library
Alexander Stepanov (https://en.wikipedia.org/wiki/Alexander_Stepanov). He
introduced the term in his book Fundamentals of Generic Programming.
Here is a short excerpt (http://stepanovpapers.com/DeSt98.pdf). It’s quite
easy to remember the eight concepts used to define a regular type. First,
there is the well-known rule of six
(https://www.modernescpp.com/index.php/c-core-guidelines-constructors-
assignments-and-desctructors):

Default constructor: X()


Copy constructor: X(const X&)

Copy assignment: operator=(const X&)

Move constructor: X(X&&)


Move assignment: operator=(X&&)

Destructor: ~X()

Second, add the Swappable and EqualityComparable concepts to it. There is a


more informal way to say that a type T is regular: T behaves like an int .

To get SemiRegular, we have to subtract EqualityComparable from Regular.

References are not Regular#


Thanks to the type-traits
(https://www.educative.io/collection/page/10370001/5799373671759872/6380
229176066048) library the following program checks at compile-time if int&
is a SemiRegular type.

Let’s have a look at the example:

1 #i l d i t
https://www.educative.io/courses/generic-templates-in-cpp/B8j9KY0g2ON 2/7
3/20/22, 6:58 PM Define your Concept: Regular and SemiRegular - Generic Programming Templates in C++
1 #include <iostream>
2 #include <type_traits>
3
4 int main(){
5     
6     std::cout << std::boolalpha << std::endl;
7     
8     std::cout << "std::is_default_constructible<int&>::value: " << std::is_default_c
9     std::cout << "std::is_copy_constructible<int&>::value: " << std::is_copy_constru
10     std::cout << "std::is_copy_assignable<int&>::value: " << std::is_copy_assignable
11     std::cout << "std::is_move_constructible<int&>::value: " << std::is_move_constru
12     std::cout << "std::is_move_assignable<int&>::value: " << std::is_move_assignable
13     std::cout << "std::is_destructible<int&>::value: " << std::is_destructible<int&>
14     std::cout << std::endl;
15     //std::cout << "std::is_swappable<int&>::value: " << std::is_swappable<int&>::va
16
17     std::cout << std::endl;
18 }

Output 1.28s

std::is_default_constructible<int&>::value: false

std::is_copy_constructible<int&>::value: true

std::is_copy_assignable<int&>::value: true

std::is_move_constructible<int&>::value: true

std::is_move_assignable<int&>::value: true

std::is_destructible<int&>::value: true

First of all, the function std::is_swappable requires C++17 that’s why we


have commented it out otherwise it will give an error. We see that the
reference such as int& is not default-constructible. The output shows that a
reference is not SemiRegular and, therefore, not Regular. To check, if a type
is Regular at compile-time, we need a function isEqualityComparable which
https://www.educative.io/courses/generic-templates-in-cpp/B8j9KY0g2ON 3/7
3/20/22, 6:58 PM Define your Concept: Regular and SemiRegular - Generic Programming Templates in C++

is not part of the type-traits library. Let’s define it.

1 #include <experimental/type_traits>                                                 
2 #include <iostream>
3
4 template<typename T>
5 using equal_comparable_t = decltype(std::declval<T&>() == std::declval<T&>());      
6
7 template<typename T>
8 struct isEqualityComparable: 
9        std::experimental::is_detected<equal_comparable_t, T>{};                     
10
11 struct EqualityComparable { };                                                      
12 bool operator == (EqualityComparable const&, EqualityComparable const&) { return tru
13
14 struct NotEqualityComparable { };                                                   
15  
16 int main() {
17     
18     std::cout << std::boolalpha << std::endl;
19     
20     std::cout << "isEqualityComparable<EqualityComparable>::value: " << 
21                   isEqualityComparable<EqualityComparable>::value << std::endl;
22                   
23     std::cout << "isEqualityComparable<NotEqualityComparable>::value: " << 
24                   isEqualityComparable<NotEqualityComparable>::value << std::endl;
25     
26     std::cout << std::endl;
27     
28 }

Output 1.47s

isEqualityComparable<EqualityComparable>::value: true

isEqualityComparable<NotEqualityComparable>::value: false

https://www.educative.io/courses/generic-templates-in-cpp/B8j9KY0g2ON 4/7
3/20/22, 6:58 PM Define your Concept: Regular and SemiRegular - Generic Programming Templates in C++

The new feature is in the experimental namespace in line 1. Line 9 is a


crucial one. It detects at compile-time if the expression in line 5 is valid for
the type T . The type-trait isEqualityComparable works for an
EqualityComparable (line 11) and a NotEqualityComparable (line 14) type.
Only EqualityCompable returns true because we overloaded the Equal-
Comparison operator.

Now, we have all the ingredients to define Regular and SemiRegular. Here
are our new type-traits.

1 #include <experimental/type_traits>
2 #include <iostream>
3
4 template<typename T>
5 using equal_comparable_t = decltype(std::declval<T&>() == std::declval<T&>());
6
7 template<typename T>
(/learn)
8 struct isEqualityComparable: 
9        std::experimental::is_detected<equal_comparable_t, T>
10        {};
11
12 template<typename T>
13 struct isSemiRegular: std::integral_constant<bool,
14                                       std::is_default_constructible<T>::value &&
15                                       std::is_copy_constructible<T>::value &&
16                                       std::is_copy_assignable<T>::value &&
17                                       std::is_move_constructible<T>::value &&
18                                       std::is_move_assignable<T>::value &&
19                                       std::is_destructible<T>::value &&
20                                       std::is_swappable<T>::value >{};
21                                       
22 template<typename T>
23 struct isRegular: std::integral_constant<bool, 
24                                          isSemiRegular<T>::value &&
25                                          isEqualityComparable<T>::value >{};
26                                          
27                                             
28 int main(){
29     
30     std::cout << std::boolalpha << std::endl;
31                   
32     std::cout << "isSemiRegular<int>::value: " << isSemiRegular<int>::value << std::
33     std::cout << "isRegular<int>::value: " << isRegular<int>::value << std::endl;
https://www.educative.io/courses/generic-templates-in-cpp/B8j9KY0g2ON 5/7
3/20/22, 6:58 PM Define your Concept: Regular and SemiRegular - Generic Programming Templates in C++
33     std::cout <<  isRegular<int>::value:   << isRegular<int>::value << std::endl;
34     
35     std::cout << std::endl;
36     
37     std::cout << "isSemiRegular<int&>::value: " << isSemiRegular<int&>::value << std
38     std::cout << "isRegular<int&>::value: " << isRegular<int&>::value << std::endl;
39     
40     std::cout << std::endl;
41     
42 }

Output 1.31s

isSemiRegular<int>::value: true

isRegular<int>::value: true

isSemiRegular<int&>::value: false
isRegular<int&>::value: false

The usage of the new type-traits isSemiRegular and isRegular makes the
main program quite readable.

In this chapter, we have learned about the future concept of C++20. Let’s
move on to the next lesson for the conclusion of this course.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022
https://www.educative.io/courses/generic-templates-in-cpp/B8j9KY0g2ON 6/7
3/20/22, 6:58 PM Define your Concept: Regular and SemiRegular - Generic Programming Templates in C++

Back Next

Define your Concepts: Equal and Ord Conclusion

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/B8j9KY0g2ON 7/7
3/20/22, 6:58 PM Conclusion - Generic Programming Templates in C++

(/learn)

Conclusion
Author's concluding words regarding the course.

This course includes all the information that you should know about
templates as a professional C++ developer. I know, sometimes the details are
quite sophisticated and, therefore, the course was not so easy to follow. This
holds, particularly true for the design with templates. But the reward is
outstanding.

Templates are one of the outstanding features of C++. They become more
and more important with each new C++ standard. The reason is quite
simple; templates provide abstraction without an abstraction performance
penalty.

With C++20, we get concepts which will lift templates to the next level. With
concepts, template parameters support semantic categories such as
Integral , provide easy to read error messages and can be implemented as
easily as functions.

You see, the future of C++ speaks templates.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

https://www.educative.io/courses/generic-templates-in-cpp/q2njEvOVE33 1/2
3/20/22, 6:58 PM Conclusion - Generic Programming Templates in C++

Back Next

Define your Concept: Regular and Se… About the Author

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/q2njEvOVE33 2/2
3/20/22, 6:59 PM About the Author - Generic Programming Templates in C++

(/learn)

About the Author


We'll cover the following

• About Me

About Me#
I’ve worked as a software architect, team lead and instructor for about 20
years. In my spare time, I enjoy writing articles on topics such as C++,
Python, and Haskell and also enjoy speaking at conferences. In 2016, I have
decided to work for myself. I organize and lead seminars about modern C++
and Python.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022
https://www.educative.io/courses/generic-templates-in-cpp/YVXQpMEAoAp 1/2
3/20/22, 6:59 PM About the Author - Generic Programming Templates in C++

Did you complete this lesson?

YES!

Back

Conclusion

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/YVXQpMEAoAp 2/2
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++

(/learn)

- Examples
Let's look at the examples of variadic templates.

We'll cover the following

• Example 1: Variadic Template

• Explanation
• Example 2: Template Perfect Forwarding

• Explanation

Example 1: Variadic Template#


1 // templateVariadicTemplates.cpp
2
3 #include <iostream>
4
5 template <typename... Args>
6 int printSize(Args... args){
7   return sizeof ...(args);
8 }
9
10 template<int ...>
11 struct Mult;
12
13 template<>
14 struct Mult<>{
15   static const int value= 1;
16 };
17
18 template<int i, int ... tail>
19 struct Mult<i, tail ...>{
20   static const int value= i * Mult<tail ...>::value;
21 };
22
23 int main(){
https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 1/6
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++
23 int main(){
24
25   std::cout << std::endl;
26
27   std::cout << "printSize(): " << printSize() << std::endl;
28   std::cout << "printSize(template,2011,true): " << printSize("template",2011,true) 
29   std::cout << "printSize(1, 2.5, 4, 5, 10): " <<  printSize(1, 2.5, 4, 5, 10) << st
30
31   std::cout << std::endl;

Explanation#
In the above example, we have used printSize function, which prints the
number of elements (of any type) passed as arguments. It detects the
number of elements on compile-time using the sizeof operator, and in case
of an empty argument list, it returns 0.

There is a struct defined as Mult which takes arguments of integer type


and return their product. If there is no argument passed, then it returns 1
which is the neutral element for multiplication. The result is stored in the
value in the fully specialized template in lines 13 – 16. The partial
specialization in lines 18 – 21 starts the recursion, which ends with the
aforementioned fully specialization for 0. The primary template in line 10 is
never used and must, therefore, never be defined.

To visualize the template instantiation for the above-mentioned example


click here (https://cppinsights.io/lnk?
code=I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHR5cGVuYW1lLi4uI
EFyZ3M+CmludCBwcmludFNpemUoQXJncy4uLiBhcmdzKXsKICByZXR1cm4g
c2l6ZW9mIC4uLihhcmdzKTsKfQoKdGVtcGxhdGU8aW50IC4uLj4Kc3RydWN0
IE11bHQ7Cgp0ZW1wbGF0ZTw+CnN0cnVjdCBNdWx0PD57CiAgc3RhdGljIGN
vbnN0IGludCB2YWx1ZT0gMTsKfTsKCnRlbXBsYXRlPGludCBpLCBpbnQgLi4u
IHRhaWw+CnN0cnVjdCBNdWx0PGksIHRhaWwgLi4uPnsKICBzdGF0aWMgY
29uc3QgaW50IHZhbHVlPSBpICogTXVsdDx0YWlsIC4uLj46OnZhbHVlOwp9O
woKaW50IG1haW4oKXsKCiAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbDsKCiAgc
https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 2/6
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++

3RkOjpjb3V0IDw8ICJwcmludFNpemUoKTogIiA8PCBwcmludFNpemUoKSA8P

CBzdGQ6OmVuZGw7CiAgc3RkOjpjb3V0IDw8ICJwcmludFNpemUodGVtcGxh
dGUsMjAxMSx0cnVlKTogIiA8PCBwcmludFNpemUoInRlbXBsYXRlIiwyMDEx
LHRydWUpIDw8IHN0ZDo6ZW5kbDsKICBzdGQ6OmNvdXQgPDwgInByaW50
U2l6ZSgxLCAyLjUsIDQsIDUsIDEwKTogIiA8PCAgcHJpbnRTaXplKDEsIDIuNSw
gNCwgNSwgMTApIDw8IHN0ZDo6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8IHN0ZD
o6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8ICJNdWx0PDEwPjo6dmFsdWU6ICIgPD
wgTXVsdDwxMD46OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKICBzdGQ6OmNvdX
QgPDwgIk11bHQ8MTAsMTAsMTA+Ojp2YWx1ZTogIiA8PCBNdWx0PDEwLDE
wLDEwPjo6dmFsdWUgPDwgc3RkOjplbmRsOwogIHN0ZDo6Y291dCA8PCAiT
XVsdDwxLDIsMyw0LDU+Ojp2YWx1ZTogIiA8PCBNdWx0PDEsMiwzLDQsNT4
6OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW
5kbDsKCn0K&insightsOptions=cpp17&std=cpp17&rev=1.0).

Example 2: Template Perfect


Forwarding#

https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 3/6
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++

// templatePerfectForwarding.cpp

#include <iostream>

#include <utility>

template<typename T, typename ... Args>

T createT(Args&& ... args){

return T(std::forward<Args>(args) ...);

struct MyStruct{

MyStruct(int&, double&, double&&){}

friend std::ostream& operator<< (std::ostream& out, const MyStruct&){

out << "MyStruct" << std::endl;

return out;
}

};

int main(){

std::cout << std::endl;

double myDouble= createT<double>();

std::cout << "myDouble: " << myDouble << std::endl;

int myInt= createT<int>(1);

std::cout << "myInt: " << myInt << std::endl;

std::string myString= createT<std::string>("My String");

std::cout << "myString: " << myString << std::endl;

MyStruct myStruct= createT<MyStruct>(myInt, myDouble, 3.14);

std::cout << "myStruct: " << myStruct << std::endl;

std::cout << std::endl;

Explanation#
In the above example, we have created a createT function which invokes
the constructor T with the arguments args . If there is no value passed, it
invokes the default constructor. The magic of the factory function createT is
https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 4/6
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++
g y
that it can invoke each constructor. Thanks to perfect forwarding, each

value can be used such as an lvalue or an rvalue; thanks to parameter packs,


any number of arguments can be used. In the case of MyStruct , a
constructor that requires three arguments is used.

The pattern of the function template createT is exactly the pattern, factory
functions such as std::make_unique , std::make_shared , std::make_pair , or
std::make_tuple use.

In the next lesson, we’ll solve exercises related to variadic templates.

Interviewing soon? We've partnered with Hired so that companies apply to


you instead of you applying to them. See how
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022

Back Next

Variadic Templates - Exercises

Mark as Completed

Report an Issue

https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 5/6
3/20/22, 5:55 PM - Examples - Generic Programming Templates in C++

https://www.educative.io/courses/generic-templates-in-cpp/JEPE51ykBOg 6/6

You might also like