Reader small image

You're reading from  Expert C++ - Second Edition

Product typeBook
Published inAug 2023
PublisherPackt
ISBN-139781804617830
Edition2nd Edition
Right arrow
Authors (5):
Marcelo Guerra Hahn
Marcelo Guerra Hahn
author image
Marcelo Guerra Hahn

Marcelo Guerra Hahn, With over 18 years of experience in software development and data analysis, Marcelo Guerra Hahn is a seasoned expert in C++, C#, and Azure. As an Engineering Manager at Microsoft C++ Team and former leader of SoundCommerce's engineering team, Marcelo's passion for data and informed decision-making shines through. He shares his knowledge as a lecturer at esteemed institutions like Lake Washington Institute of Technology and University of Washington. Through this book, Marcelo aims to empower readers with advanced C++ techniques, honed by real-world experience, to become proficient programmers and skilled data analysts.
Read more about Marcelo Guerra Hahn

Araks Tigranyan
Araks Tigranyan
author image
Araks Tigranyan

Araks Tigranyan is a passionate software engineer at Critical Techworks, with an unwavering love for the world of programming, particularly in C++. Her dedication to crafting efficient and innovative solutions reflects her genuine passion for coding. Committed to excellence and driven by curiosity, Araks continuously explores new technologies, going above and beyond to deliver exceptional work. Beyond programming, Araks finds solace in sports, with football holding a special place in her heart. As an author, Araks aspires to share her profound expertise in C++ and inspire readers to embark on their programming journeys.
Read more about Araks Tigranyan

John Asatryan
John Asatryan
author image
John Asatryan

John Asatryan, the Head of Code Republic Lab at Picsart Academy, seamlessly blends his academic background in International Economic Relations from the Armenian State University of Economics with his ventures in technology and education. Driven by a genuine passion for coding, John's commitment to empowering aspiring developers is evident in his expertise in the field. His unwavering dedication to bridging the gap between education and technology inspires others to pursue their coding dreams.
Read more about John Asatryan

Vardan Grigoryan
Vardan Grigoryan
author image
Vardan Grigoryan

Vardan Grigoryan is a senior backend engineer and C++ developer with more than 9 years of experience. Vardan started his career as a C++ developer and then moved to the world of server-side backend development. While being involved in designing scalable backend architectures, he always tries to incorporate the use of C++ in critical sections that require the fastest execution time. Vardan loves tackling computer systems and program structures on a deeper level. He believes that true excellence in programming can be achieved by means of a detailed analysis of existing solutions and by designing complex systems.
Read more about Vardan Grigoryan

Shunguang Wu
Shunguang Wu
author image
Shunguang Wu

Shunguang Wu is a senior professional staff at Johns Hopkins University Applied Physics Laboratory, and received his PhDs in theoretical physics and electrical engineering from Northwestern University (China) and Wright State University (USA), respectively. He published about 50 reviewed journal papers in the area of nonlinear dynamics, statistical signal processing and computer vision in his early career. His professional C++ experience started with teaching undergraduate courses in the late 1990s. Since then he has been designing and developing lots of R&D and end-user application software using C++ in world-class academic and industrial laboratories. These projects span both the Windows and Linux platforms.
Read more about Shunguang Wu

View More author details
Right arrow

Understanding and Designing Templates

Templates are a unique feature of C++ by which functions and classes have the ability to support generic data types—in other words, we can implement a function or class independent of a particular data type; for example, a client may request a max() function to handle different data types. Instead of implementing and maintaining many similar functions by using function overloading, we can just implement one max() function and pass the data type as a parameter. Moreover, templates can work together with multiple inheritance and operator overloading to create powerful generic data structures and algorithms in C++ such as the Standard Template Library (STL). Additionally, templates can also be applied to compile-time computation, compile-time and runtime code optimization, and more.

In this chapter, we will learn about the syntax of function and class templates, their instantiations, and their specializations. Then, we will introduce variadic...

Technical requirements

The code for this chapter can be found in this book’s GitHub repository:

https://github.com/PacktPublishing/Expert-CPP/tree/master/Chapter03

Motivation for using templates

So far, when we have defined a function or a class, we have had to provide input, output, and intermediate parameters. For example, let’s say we have a function to perform the addition of two int-type integers. How do we extend this so that it handles all the other basic data types, such as float, double, char, and so on? One way is to use function overloading by manually copying, pasting, and slightly modifying each function. Another way is to define a macro to do the addition operation. Both approaches have their side effects.

Moreover, what happens if we fix a bug or add a new feature for one type, and this update needs to be done for all the other overloading functions and classes later? Instead of using this silly copy-paste-and-replacement method, do we have a better way of handling this kind of situation?

In fact, this is a generic problem that any computer language can face. Pioneered by the general-purpose functional programming...

Function templates

A function template defines how a family of functions can be generated. A family here means a group of functions that behave similarly. As shown in Figure 3.1 and outlined next, this includes two phases:

Figure 3.1 – Function template format

Figure 3.1 – Function template format

  • Creating a function template, that is, the rules on how to write it
  • Template instantiation, that is, the rules that are used to generate functions from their template

In part I of the preceding diagram, we discuss the format that will be used to create a function template for generic types, but with respect to the specialized template, which we also refer to as the primary template. Then, in part II, we introduce the three ways to generate functions from the template. Lastly, the Specialization and overloading subsection in this chapter tells us how to customize the primary template (by changing its behavior) for special types. In the following subsections, we will delve into...

Class templates

A class template defines a family of classes, and it is often used to implement a container. For example, the C++ Standard Library contains many class templates, such as std::vector, std::map, std::deque, and so on. In OpenCV, cv::Mat is a very powerful class template, and it can handle 1D, 2D, and 3D matrices or images with built-in data types such as int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, float, double, and so on.

Similar to function templates, as shown in Figure 3.2, the concept of class templates contains a template creation syntax, its specialization, and its implicit and explicit instantiations:

Figure 3.2 – Class template and its instantiation

Figure 3.2 – Class template and its instantiation

In part I of the preceding diagram, with a certain syntax format, we can create a class template for generic types, also known as a primary template, and it can be customized for special types with different member functions and/or variables. Once we have a class template...

Understanding variadic templates

In the previous section, we learned how to write function or class templates with a fixed number of type parameters. But since C++11, standard generic functions and class templates can accept a variable number of type parameters. This is called variadic templates, which is an extension of C++ (see the link in the Further reading section, context [6]. We will learn about the syntax and usage of variadic templates by looking at examples.

Syntax

If a function or class template takes zero or more parameters, it can be defined as follows:

//a class template with zero or more type parameterstemplate <typename... Args>
class X {
...
};
//a function template with zero or more type parameters
template <typename... Args>
void foo( function param list) {
…
}

Here, <typename ... Args> declares a parameter pack. Note that here, Args is not a keyword; you can use any valid variable name. The preceding class/function template can...

Exploring template parameters and arguments

We learned about function and class templates and their instantiations in the previous three sections. We know that, when defining a template, its parameter list needs to be given. While we instantiate it, the corresponding argument list must be provided. In this section, we will further study the classifications and details of these two lists.

Template parameters

Recall the following syntax, which is used to define a class/function template. There is a <> symbol after the template keyword, in which one or more template parameters must be given:

//class template declarationtemplate <parameter-list> class-declaration
//function template declaration
template <parameter-list> function-declaration

A parameter inside the parameter list could be one of the following three types:

  • Non-type template parameter: Refers to the compile-time constant values, such as integers and pointers, that reference static entities...

Traits

Generic programming means writing code that works with any data type under certain requirements. It is the most efficient way of delivering reusable high-quality code in the software engineering industry. However, there are times in generic programming when being generic just isn’t good enough. Whenever the differences between types are too complex, it is very hard for an efficient generic to optimize a common implementation. For example, while implementing a sort function template, if we know the argument type is a linked list but not an array, a different strategy will be implemented to optimize the performance.

Although template specialization is one approach to overcoming this problem, it doesn’t provide type-related information in a broad way. A type trait is a technique that’s used to collect information about the type. With its help, we can make more intelligent decisions to develop high-quality optimized algorithms in generic programming.

In...

Type trait implementation

To understand type traits, we’ll look at the classic implementations of boost::is_void and boost::is_pointer.

boost::is_void

First, let’s look at one of the simplest traits classes, the is_void trait, which was created by Boost. It defines a generic template that’s used to implement the default behavior; that is, accept a void type, but not anything else. Hence, we have is_void::value = false:

//primary class template is_voidtemplate< typename T >
struct is_void{
static const bool value = false; //default value=false
};

Then, we fully specialize it for the void type, like so:

//"<>" means a full specialization of template class is_voidtemplate<>
struct is_void< void >{ //fully specialization for void
static const bool value = true; //only true for void type
};

Thus, we have a complete traits type that can be used to detect whether any given type, T, is void by checking the following expression...

Optimizing algorithms using traits

Instead of talking about this topic in a generic abstract way, we will use a classic optimized copy example to show the usage of type traits. Consider the standard library algorithm known as copy, shown here:

template<typename It1, typename It2>It2 copy(It1 first, It1 last, It2 out);

Obviously, we can write a generic version of copy() for any iterator types—that is, It1 and It2 here. However, as explained by the authors of the Boost library, there are some circumstances where the copy operation can be performed by memcpy(). We can use memcpy() if all of the following conditions are satisfied:

  • Both types of iterators, It1 and It2, are pointers
  • It1 and It2 must point to the same type, except for const and volatile qualifiers
  • A trivial assignment operator must be provided by the type that It1 points to

Here, the trivial assignment operator means that the type is either a scalar type or that one of the following...

TMP and its applications

A programming technique in which computer programs have the ability to treat other programs as their data is known as metaprogramming. This means that a program can be designed to read, generate, analyze, or transform other programs, and even modify itself while running. One kind of metaprogramming is a compiler, which takes a text format program as an input language (C, Fortran, Java, and so on) and produces another binary machine code format program in an output language.

C++ TMP means producing metaprograms in C++ using templates. It has two components—a template must be defined, and a defined template must be instantiated. TMP is Turing-complete, which means it has the capability to compute anything computable, at least in principle. Also, because variables are all immutable (variables are constants) in TMP, recursion rather than iteration is used to process the elements of a set.

Why do we need TMP? Because it can speed up our programs during...

Summary

In this chapter, we discussed generic programming-related topics in C++. Starting by reviewing C macros and function overloading, we introduced the development motivations of C++ templates. Then, we presented the syntax of class and function templates with a fixed number of parameters, as well as their specializations and instantiations. Since C++11, variadic templates are accepted by the standard generic function and class templates. Based on this, we further classified the template parameters and arguments into three categories: non-type template parameters/arguments, type template parameters/arguments, and template template parameters/arguments.

We also learned about traits and TMP. As a byproduct of template specialization, traits classes can provide us with more information about types. With the help of type information, eventually, the optimizations of implementing generic algorithms become possible. Another application of class and/or function templates is to compute...

Questions

  1. What are the negative side effects of macros and function overloading?
  2. What is a class/function template? What is a template class/function?
  3. What is a template parameter list? What is a template argument list? Once we have a class template, we can instantiate it either explicitly or implicitly. In what kind of scenario is explicit instantiation necessary?
  4. What does polymorphism mean in C++? What is the difference between function overloading and function overriding?
  5. What are type traits? How do we implement a type trait?
  6. In the 5_class_template_implicit_inst_B.cpp file, we said implicit instantiation generates the X<int> class, and then creates an xi object and generates the X<int>::f() function, but not X<int>::g(). How can you verify that X<int>::g() is not generated?
  7. Using TMP, solve the problem of f(x,n) = x^n, where n is a const and x is a variable.
  8. Extend 16_loop_unrolling_traditional.cpp and 17_loop_unrolling_metaprogramming...

Further reading

As referenced throughout this chapter, have a look at the following sources to find out more regarding what was covered in this chapter:

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Expert C++ - Second Edition
Published in: Aug 2023Publisher: PacktISBN-13: 9781804617830
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Authors (5)

author image
Marcelo Guerra Hahn

Marcelo Guerra Hahn, With over 18 years of experience in software development and data analysis, Marcelo Guerra Hahn is a seasoned expert in C++, C#, and Azure. As an Engineering Manager at Microsoft C++ Team and former leader of SoundCommerce's engineering team, Marcelo's passion for data and informed decision-making shines through. He shares his knowledge as a lecturer at esteemed institutions like Lake Washington Institute of Technology and University of Washington. Through this book, Marcelo aims to empower readers with advanced C++ techniques, honed by real-world experience, to become proficient programmers and skilled data analysts.
Read more about Marcelo Guerra Hahn

author image
Araks Tigranyan

Araks Tigranyan is a passionate software engineer at Critical Techworks, with an unwavering love for the world of programming, particularly in C++. Her dedication to crafting efficient and innovative solutions reflects her genuine passion for coding. Committed to excellence and driven by curiosity, Araks continuously explores new technologies, going above and beyond to deliver exceptional work. Beyond programming, Araks finds solace in sports, with football holding a special place in her heart. As an author, Araks aspires to share her profound expertise in C++ and inspire readers to embark on their programming journeys.
Read more about Araks Tigranyan

author image
John Asatryan

John Asatryan, the Head of Code Republic Lab at Picsart Academy, seamlessly blends his academic background in International Economic Relations from the Armenian State University of Economics with his ventures in technology and education. Driven by a genuine passion for coding, John's commitment to empowering aspiring developers is evident in his expertise in the field. His unwavering dedication to bridging the gap between education and technology inspires others to pursue their coding dreams.
Read more about John Asatryan

author image
Vardan Grigoryan

Vardan Grigoryan is a senior backend engineer and C++ developer with more than 9 years of experience. Vardan started his career as a C++ developer and then moved to the world of server-side backend development. While being involved in designing scalable backend architectures, he always tries to incorporate the use of C++ in critical sections that require the fastest execution time. Vardan loves tackling computer systems and program structures on a deeper level. He believes that true excellence in programming can be achieved by means of a detailed analysis of existing solutions and by designing complex systems.
Read more about Vardan Grigoryan

author image
Shunguang Wu

Shunguang Wu is a senior professional staff at Johns Hopkins University Applied Physics Laboratory, and received his PhDs in theoretical physics and electrical engineering from Northwestern University (China) and Wright State University (USA), respectively. He published about 50 reviewed journal papers in the area of nonlinear dynamics, statistical signal processing and computer vision in his early career. His professional C++ experience started with teaching undergraduate courses in the late 1990s. Since then he has been designing and developing lots of R&D and end-user application software using C++ in world-class academic and industrial laboratories. These projects span both the Windows and Linux platforms.
Read more about Shunguang Wu