Templates allow us to write functions or classes using placeholder types, so that we can stencil out identical versions of the function or class using different types. A function or class that has been instantiated is called a function or class instance.
All template functions or classes must start with a template parameter declaration that tells the compiler that the following function or class is a template function or class. Within the template parameter declaration, the template type parameters or expression parameters are specified. Template type parameters are just placeholder types, normally named T, T1, T2, or other single letter names (e.g. S). Expression parameters are usually integral types, but can be a pointer or reference to a function, class object, or member function.
Splitting up template class definition and member function definitions doesn’t work like normal classes -- you can’t put your class definition in a header and member function definitions in a .cpp file. It’s usually best to keep all of them in a header file, with the member function definitions underneath the class.
Template specialization can be used when we want to override the default behavior from the templated function or class for a specific type. If all types are overridden, this is called full specialization. Classes also support partial specialization, where only some of the templated parameters are specialized. Functions do not support partial specialization as of C++14.
Many classes in the C++ standard library use templates, including std::array and std::vector. Templates are often used for implementing container classes, so a container can be written once and used with any appropriate type.
Quiz time
1) It’s sometimes useful to define data that travels in pairs. Write a templated class named Pair1 that allows the user to define one template type that is used for both values in the pair. The following function should work:
1 2 3 4 5 6 7 8 9 10 |
int main() { Pair1<int> p1(5, 8); std::cout << "Pair: " << p1.first() << ' ' << p1.second() << '\n'; const Pair1<double> p2(2.3, 4.5); std::cout << "Pair: " << p2.first() << ' ' << p2.second() << '\n'; return 0; } |
and print:
Pair: 5 8 Pair: 2.3 4.5
2) Write a Pair class that allows you to specify separate types for each of the two values in the pair.
Note: We’re naming this class differently from the previous one because C++ does not currently allow you to “overload” classes that differ only in the number or type of template parameters.
The following program should work:
1 2 3 4 5 6 7 8 9 10 |
int main() { Pair<int, double> p1(5, 6.7); std::cout << "Pair: " << p1.first() << ' ' << p1.second() << '\n'; const Pair<double, int> p2(2.3, 4); std::cout << "Pair: " << p2.first() << ' ' << p2.second() << '\n'; return 0; } |
and print:
Pair: 5 6.7 Pair: 2.3 4
Hint: To define a template using two different types, separate the two types by a comma in the template parameter declaration. See lesson 19.1 -- Function templates for more information.
3) A string-value pair is a special type of pair where the first value is always a string type, and the second value can be any type. Write a template class named StringValuePair that inherits from a partially specialized Pair class (using std::string as the first type, and allowing the user to specify the second type).
The following program should run:
1 2 3 4 5 6 7 |
int main() { StringValuePair<int> svp("Hello", 5); std::cout << "Pair: " << svp.first() << ' ' << svp.second() << '\n'; return 0; } |
and print:
Pair: Hello 5
Hint: When you call the Pair constructor from the StringValuePair constructor, don’t forget to include the template parameters as part of the Pair class name.
![]() |
![]() |
![]() |
1. Feedback and Query
This key value pattern was not mentioned in Chapter 19.
It only exists in the Quiz.
I hope this is acceptable.
This chapter has been super amazing!
Thank you a lot and a lot!
I am guessing HashMap in C++ is somehow implemented like StringValuePair, right?
There is no hashmap in the standard library. You can implement one yourself by means of `std::hash` and a standard container (eg. `std::vector`).
Please disregard what I said, `std::unordered_map` is C++'s hashmap. It uses `std::pair` internally.
How do we use the hash table/function and std::unordered_map?
It's not mentioned in the tutorial.
In the solutions for 1 and 2 the parameters of the constructor and the return type of first() and second() are const refs. Since int and double are basic types I assumed passing as value would be better (as opposed to passing as reference).
What is the reason for using const &?
Thanks for the amazing material!
Those are template classes. Unless you write a specialized class (Pair isn't specialized), you must assume that the class will be used with any type. The benefit of using references for non-fundamental types outweighs the cost of using references for fundamental types.
Hi sir, i moved to learning assembly after Chap 13. And "linked lists" seems to be an important part while reversing code into C++. I don't remember studying it till chap 13. Could u tell me on which chapter number "Linked lists" come under ? I checked the index section but couldn't find it. Is there any chapter after 13 which i should be familiar with before learning linked lists ?
All you need for linked lists are classes and pointers. The standard container for linked lists, `std::list`, is not covered on learncpp.
Why do you think linked lists are important for reversing/assembly?
Oh ok sir. Oops sorry, i meant to say its important for doing malware analysis. I am learning analysis and couldn't figure out the assembly code that represented linked lists. Ofcourse i need to understand all d assembly code, but the course insisted that linked lists are one of the basic things i must know.
Thank you :) always the best place to understand everything
i'm still a little confused
when to use
and when to use
i know you said typename and class are like synonyms but their may be a standard way...is there?
There's no difference. Pick one and use it consistently or make up a rule when to use which of the two.
Hi nascardriver,
I tried to add this function in StringValuePair class
and I got this error:" 'm_x undeclared identifier' ". Also I defined m_x and m_y as protected in "Pair" class. So what is the problem? why I can't access m_x?
Identifiers aren't looked up in templated base classes. `m_x` is a member of `Pair`, which is a templated parent of `StringValuePair`.
To allow `m_x` to be looked up in the base class, use `this->m_x`.
this because of the fact that the template will be compiled twice(two phases look-up). In the first phase(for syntax), the compiler doesn't know what is m_x, since the template is just a blueprint and nothing has been instantiated yet, am I right?
thanks in advance
Correct. When you use just `m_x`, there's no connection from `m_x` to `T` (`m_x` doesn't depend on `T`), so the compiler doesn't try to instantiate the base template. When you use `this->m_x`, `m_x` becomes dependent on `T` (Because `this` depends on `T`).
Hello! I have a suggestion for this chapter: variadic templates and why you should consider using them over the regular (...) and va_* macros (i.e. their type safety, and the fact that everything can be resolved at compile time, as opposed to runtime). However, I'm sure that covering the stuff in C++20 would take higher precedence over adding a lesson on variadic templates. Still, it would be cool ! :D