Generic Programming
Generic Programming
Generic Programming
(/learn)
Function Templates
In this lesson, we'll explore function templates in detail.
• Function Templates
• 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.
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:
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.
func<type>(...)
4. You can specify that you are only interested in a specific instantiation of
a function template.
func<>(...)
Back Next
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.
• Explanation
• Example 2: Overloading Function Templates
• Explanation
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
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.
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
Before: 10, 5, 20
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.
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
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.
• 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.
• Explanation
• Solution 2: Using Template Arguments
• Explanation
• Solution 3: Using Template Arguments and Function Arguments
• Explanation
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.
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).
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.
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.
Back Next
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
• Explanation
• Solution 2: Using Template Arguments
• Explanation
• Solution 3: Using Template Arguments and Function Arguments
• Explanation
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.
#include <iostream>
struct Power{
};
template<int m>
struct Power<m,0>{
};
int main(){
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).
#include <iostream>
template<int n>
template<>
return m;
template<>
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(){
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.
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.
Back Next
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.
• Syntax
• Explanation
• Instantiation
• Method Templates
• Inheritance
• 3 Solutions:
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.
Instantiation#
The process of substituting the template parameters with the template
arguments is called instantiation .
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 }
Inheritance#
Class and class template can inherit from each other in arbitrary
combinations.
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
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++
, ;
In the next lesson, we’ll learn about the examples of class templates.
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.
• Explanation
• Example 2: Inheritance in Class Templates
• Explanation
• Example 3: Methods in Class Templates
• Explanation
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.
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.
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 .
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.
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
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.
• 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
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.
• 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++
Back Next
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.
• 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.
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.
Non-Types#
Non-types are template parameters which can be evaluated at compile-time.
std::nullptr_t constant
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.
• Explanation
• Example 2: Non-Type Template Parameter
• Explanation
• Example 3: Template-Template Parameter
• Explanation
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.
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.
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
myDoubleVec.getSize(): 5
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.
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022
Back Next
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.
• 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++
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.
• 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++
Back Next
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.
• 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:
void func(ParamType param);
ParamType
ParamType can be
Reference or pointer
template <typename T>
void func(T& param);
// void func(T* param);
func(expr);
template <typename T>
void func(T&& param);
func(expr);
template <typename T>
func(expr);
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.
isSmaller(1, 5LL); // OK
template <typename R, typename T, typename U>
R add(T fir, U sec){
return fir * sec;
add<long long int>(1000000, 1000000LL);
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);
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.
• Explanation
• Example 2: Template Default Arguments
• Explanation
• Example 3: Function Template Argument Deduction by Reference
• Explanation
• Explanation
• Example 5: Function Template Argument Deduction by Value
• Explanation
Output 1.65s
isSmaller(1,2): true
isSmaller<int>(1,5LL): true
isSmaller<double>(1,5LL): true
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.
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.
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).
https://www.educative.io/courses/generic-templates-in-cpp/m20Mg8J806A 6/10
3/20/22, 8:01 PM - Examples - Generic Programming Templates in C++
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++
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.
Back Next
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.
• Problem Statement
Problem Statement#
The class Matrix holds its values in the container Cont .
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
myStringList.getSize(): 4
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.
• 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
myDoubleVec.getSize(): 5
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++
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.
• Specialization
• Primary Template
• Partial 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.
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++
Primary Template#
The primary template has to be declared before the partially or fully
specialized templates.
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)
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.
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.
(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 <> .
struct Matrix;
template <>
};
// template <>
return 3 * 3;
};
(https://en.cppreference.com/w/cpp/language/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.
• Explanation
• Example 2: Template Specialization External
• Explanation
• Example 3: Template Specialization Full
• Explanation
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).
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).
Output 1.52s
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).
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.
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.
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.
• Problem Statement
Problem Statement#
The class template Type in the code below returns to each type the name
unknown .
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 }
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.
• 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++
Back Next
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.
• 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.
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.
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.
• Explanation
Output 1.89s
implicit
vec.size(): 0
arr.getSize(): 10
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.
Back Next
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.
• 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?
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++
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.
• 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.
Back Next
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.
• 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.
the ellipse is right from Args , the parameter pack will be unpacked.
The usage of parameter packs obeys a typical pattern for class templates.
1 template<>
2 struct Mult<>{ .... }
3 template<int i, int ... tail >
4 struct Mult<i, tail ...>{ ....
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.
• Explanation
• Example 2: Template Perfect Forwarding
• Explanation
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.
3RkOjpjb3V0IDw8ICJwcmludFNpemUoKTogIiA8PCBwcmludFNpemUoKSA8P
CBzdGQ6OmVuZGw7CiAgc3RkOjpjb3V0IDw8ICJwcmludFNpemUodGVtcGxh
dGUsMjAxMSx0cnVlKTogIiA8PCBwcmludFNpemUoInRlbXBsYXRlIiwyMDEx
LHRydWUpIDw8IHN0ZDo6ZW5kbDsKICBzdGQ6OmNvdXQgPDwgInByaW50
U2l6ZSgxLCAyLjUsIDQsIDUsIDEwKTogIiA8PCAgcHJpbnRTaXplKDEsIDIuNSw
gNCwgNSwgMTApIDw8IHN0ZDo6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8IHN0ZD
o6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8ICJNdWx0PDEwPjo6dmFsdWU6ICIgPD
wgTXVsdDwxMD46OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKICBzdGQ6OmNvdX
QgPDwgIk11bHQ8MTAsMTAsMTA+Ojp2YWx1ZTogIiA8PCBNdWx0PDEwLDE
wLDEwPjo6dmFsdWUgPDwgc3RkOjplbmRsOwogIHN0ZDo6Y291dCA8PCAiT
XVsdDwxLDIsMyw0LDU+Ojp2YWx1ZTogIiA8PCBNdWx0PDEsMiwzLDQsNT4
6OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW
5kbDsKCn0K&insightsOptions=cpp17&std=cpp17&rev=1.0).
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>
struct MyStruct{
return out;
}
};
int main(){
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
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.
Back Next
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.
• 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++
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.
• Explanation
Output 1.58s
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.
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022
Back Next
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.
• Two variations
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 }
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
Logical OR || false
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 .
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);
In the next lesson, we’ll have a look at the examples of fold expressions.
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.
• Explanation
• Example 2: String Concatenation
• Explanation
Output 1.38s
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.
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.
Back Next
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.
• Explanation
• Example 2: String Concatenation
• Explanation
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
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.
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.
Back Next
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.
• Explanation
• Example 2: String Concatenation
• Explanation
Output 1.37s
all(true): true
any(true): true
none(true): 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.
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.
Back Next
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.
• Problem Statement
Problem Statement#
Write two sum functions which use the fold expressions to add all the values
passed as arguments:
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++
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.
• 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.
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.
• Friends
• General Friends
• Special Friends
• Friend to Types
Friends#
Friends of a class template have access to all members of the class template.
Rules:
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 ...
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++
Friend to Types#
A class template can grant its friendship to a type parameter.
template <typename T>
class Array{
friend T;
...
};
Array<Account> myAccount;
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.
• Explanation
• Example 2: Class Template Special Friendship
• Explanation
• Example 3: Class Template Type Friendship
• Explanation
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
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.
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
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.
Output 1.28s
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++
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.
• 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.
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.
• 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.
Back Next
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.
• Dependent Names
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.
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.
Type
Non-type
Template
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)
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 .
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.
• Explanation
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.
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
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++
template <typename T1, typename T2>
auto add(T1 fir, T2 sec) -> decltype( fir + sec ) {
return fir + sec;
Rules:
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)
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)
template <typename T1, typename T2>
auto add(T1 fir, T2 sec){
return fir + sec;
Rules
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++
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.
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.
• Explanation
Output 1.25s
add(1, 1)= 2
typeid(add(1, 1)).name()= i
typeid(add(1, 2.1)).name()= d
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.
Back Next
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.
• Problem Statement
Problem Statement#
The two algorithms gcdConditional and gcdCommon , in the given code, use the
type-traits library.
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.
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.
• 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++
Back Next
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.
• Template Metaprogramming
• Type Manipulations
• Explanation
Template Metaprogramming#
(/learn)
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;
Assembler Instructions
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.
229176066048).
template <>
struct Factorial<1>{
static int const value = 1;
};
template <typename T>
struct RemoveConst<const T>{
typedef T type;
};
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++
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;
};
int main(){
std::cout << power(2, 10) << std::endl; // 1024
std::cout << Power<2, 10>::value << std::endl; // 1024
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++
C++03: 17
C++11: 1024
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.
• Explanation
• Example 2: Template Type Manipulation
• Explanation
• Example 3: Template Power
• Explanation
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.
Output 2.48s
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).
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.
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
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.
• 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
https://www.educative.io/courses/generic-templates-in-cpp/39QDv3WJAQr 1/2
3/20/22, 6:16 PM - Exercise - Generic Programming Templates in C++
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.
• 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.
Back Next
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.
• 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.
Programming at compile-time
Programming with types and values
#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 .
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;
std::is_pointer<T>,
std::is_integral<T>,
std::is_floating_point<T>
std::is_arithmetic<T>,
std::is_object<T>
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>
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
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.
Back Next
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++
• Correctness
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.
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
| ^
4 | T gcd(T a, T b){
| ^~~
| ^
| ~~^~~
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.
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
| ^~~~~
| ~~^~~
| ^~~~~
| ~~^~~
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.
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.
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 .
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 .
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
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
20 | std::cout << "gcd(3.5, 4.0)= " << gcd(3.5, 4.0) << std::endl;
| ^
8 | R gcd(T1 a, T2 b){
| ^~~
| ^
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.
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++
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
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++
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 }
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.
Back Next
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.
• Explanation
• Example 2: Template Type Manipulation
• Explanation
Output 2.15s
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++
Output 2.01s
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.
Back Next
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.
• 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.
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++
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.
• 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<myConstInt>::value: true
(/learn)
(fir, refFi1r, refFir2): (1, 1, 1)
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.
https://www.educative.io/courses/generic-templates-in-cpp/xV5Rm5YB9Zl 2/3
3/20/22, 6:22 PM - Solution - Generic Programming Templates in C++
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.
• Constant Expressions
• User-Defined Types
• Example
• Functions
• Examples
• Functions with C++14
• constexpr Functions in C++14
• Example
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
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;
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 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
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++
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.
The function
has to be non-virtual.
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);
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
Programming
Functional Imperative
paradigm
Modification No Yes
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
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.
• Explanation
• Example 2: constexpr function in C++ 14
• Explanation
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.
(/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.
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.
• 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++
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.
• constexpr if (C++17)
constexpr if (C++17)#
constexpr if enables us to compile source code
conditionally.
if constexpr (cond) statement1;
else statement2;
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++
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.
• 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.
https://www.educative.io/courses/generic-templates-in-cpp/7XPOJYAKrgQ 3/4
3/20/22, 6:25 PM - Example - Generic Programming Templates in C++
Back Next
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)
• Polymorphism
Polymorphism#
Polymorphism means that an object can have different behaviors.
Dynamic Polymorphism
Static 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++
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.
• Explanation
• Example 2: Dispatch with Static Polymorphism
• Explanation
Output 1.65s
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).
(/learn)
Output 1.28s
https://www.educative.io/courses/generic-templates-in-cpp/m78xylop9wA 5/7
3/20/22, 6:28 PM - Examples - Generic Programming Templates in C++
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.
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
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.
• 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.
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.
• Explanation
• Solution 2: Using the switch statement
• Explanation
• Solution 3: Using a Dispatch Table
• Explanation
Output 2.51s
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#
Output 1.67s
Explanation#
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.
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)
Explanation#
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.
• 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.
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++
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();
}
};
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.
• Explanation
• Example 2: Static Polymorphism with CRTP
• Explanation
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
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.
(/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).
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.
• 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.
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 }
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.
• Explanation
• Solution of Problem Statement 2
• Explanation
• Solution to Problem Statement 3 (Case 1)
• Explanation
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
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.
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
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.
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.
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).
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 .
Output 1.62s
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++
Back Next
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.
• Expression Templates
• Lazy Evaluation
• A First Naive Approach
• The Issue
• The Solution
• The Idea
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.”
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.
Advantages:
Disadvantages:
Longer compile-times
Advanced programming technique (template metaprogramming)
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
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;
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++
(/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++
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.
• Explanation
• Example 2: Vector Arithmetic Based on Expression Templates
• Explanation
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).
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++
Back Next
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.
• 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.
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 }
https://www.educative.io/courses/generic-templates-in-cpp/YV3wMxYKppp 5/6
3/20/22, 6:39 PM - Exercises - Generic Programming Templates in C++
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.
• Explanation
• Problem Statement 2: Solution
• Explanation
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.
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.
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022
Back Next
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++
• Policy
• Traits
Typical examples for policies are the containers of the Standard Template
Library such as std::vector , or std::unordered_map :
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)
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;
};
In the next lesson, we’ll look at a few examples of policy and traits in idioms
and patterns.
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.
• Explanation
• Example 2: Templates Traits
• Explanation
Output 1.45s
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++
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.
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
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.
• 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++
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 }
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.
• Explanation
• Solution Review of Problem Statement 2
• Explanation
• Solution Review of Problem Statement 3
• Explanation
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
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 .
Output 1.41s
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 .
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.
Back Next
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++
• Tag Dispatching
Tag Dispatching#
Tag Dispatching enables us to choose a function based on type
characteristics.
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 next lesson, we’ll look at an example of tag dispatching in idioms and
patterns.
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.
• Explanation
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.
(https://join.hired.com/educative/?
utm_source=educative&utm_medium=partner&utm_campaign=March_2022
Back Next
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.
• 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
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.
• 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)
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++
Back Next
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++
• Type Erasure
• Case 2: Object-Orientation
• Case 3: std::function
Type Erasure#
Type Erasure enables you to use various concrete types through a single
generic interface.
“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++
int cmp(const void *a, const void *b);
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.
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++
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:
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.
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.
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.
• Explanation
• Pros:
• Cons:
• Example 2: Type Erasure with Templates
• Explanation
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
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
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).
Back Next
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.
• 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 }
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.
• 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.
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.
• Too Specific
• Narrowing Conversion
• Integral Promotion
• Too Generic
• 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:
#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
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
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++
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
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.
Advantages#
Express the template parameter requirements as part of the interface
In the next lesson, we’ll learn about the history of C++ and talk about future
concepts.
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.
• Classical Concepts
• Concepts
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’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.
Concepts
In the next lesson, we’ll learn about the details of functions and classes with
reference to concepts.
Back Next
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
• Classes
• Methods of a Class
• More Requirements
• Overloading
• Specialization
Functions#
Using the concept Sortable .
template<Sortable Cont>
version:
void sort(Cont& container){
...
Explicit
}
template<typename Cont>
requires Sortable<Cont>()
void sort(Cont& container){
...
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 <
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.
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.
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++
Back Next
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.
• Inconsistency in C++14
• Constrained and Unconstrained Placeholders
• Example:
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.
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++
Back Next
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.
• Predefined Concept
• Concepts TS
• Concepts Draft
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:
Same Destructible
DerivedFrom Constructible
ConvertibleTo DefaultConstructible
Common MoveConstructible
Integral Copy Constructible
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.
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;
Concepts TS#
template<typename T>
concept bool Equal(){
return requires(T a, T b) {
{ a == b } -> bool;
{ a != b } -> bool;
};
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;
};
(/learn)
Output 2.01s
We used the concept Equal in the (generic) function areEqual (line 13 to 15)
and that’s not so exciting.
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.
Back Next
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++
• Eq versus Equal
Eq versus Equal #
(==) :: 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
If you compare Haskell’s type class with C++'s concept, you see the similarity.
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
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 .
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
| ^
| ^~~~~~~~~~
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: 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.
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++
Back Next
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++
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):
Destructor: ~X()
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
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++
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.
Back Next
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.
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
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 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.
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.
• Explanation
• Example 2: Template Perfect Forwarding
• Explanation
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.
3RkOjpjb3V0IDw8ICJwcmludFNpemUoKTogIiA8PCBwcmludFNpemUoKSA8P
CBzdGQ6OmVuZGw7CiAgc3RkOjpjb3V0IDw8ICJwcmludFNpemUodGVtcGxh
dGUsMjAxMSx0cnVlKTogIiA8PCBwcmludFNpemUoInRlbXBsYXRlIiwyMDEx
LHRydWUpIDw8IHN0ZDo6ZW5kbDsKICBzdGQ6OmNvdXQgPDwgInByaW50
U2l6ZSgxLCAyLjUsIDQsIDUsIDEwKTogIiA8PCAgcHJpbnRTaXplKDEsIDIuNSw
gNCwgNSwgMTApIDw8IHN0ZDo6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8IHN0ZD
o6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8ICJNdWx0PDEwPjo6dmFsdWU6ICIgPD
wgTXVsdDwxMD46OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKICBzdGQ6OmNvdX
QgPDwgIk11bHQ8MTAsMTAsMTA+Ojp2YWx1ZTogIiA8PCBNdWx0PDEwLDE
wLDEwPjo6dmFsdWUgPDwgc3RkOjplbmRsOwogIHN0ZDo6Y291dCA8PCAiT
XVsdDwxLDIsMyw0LDU+Ojp2YWx1ZTogIiA8PCBNdWx0PDEsMiwzLDQsNT4
6OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKCiAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW
5kbDsKCn0K&insightsOptions=cpp17&std=cpp17&rev=1.0).
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>
struct MyStruct{
return out;
}
};
int main(){
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
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.
Back Next
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