Assignment Answers

Chapter 1, Introduction to Templates

Question 1

Why do we need templates? What advantages do they provide?

Answer

There are several benefits to using templates: they help us avoid writing repetitive code, they foster the creation of generic libraries, and they can help us write less and better code.

Question 2

How do you call a function that is a template? What about a class that is a template?

Answer

A function that is a template is called a function template. Similarly, a class that is a template is called a class template.

Question 3

How many kinds of template parameters exist and what are they?

Answer

There are three kinds of template parameters: type template parameters, non-type template parameters, and template template parameters.

Question 4

What is partial specialization? What about full specialization?

Answer

Specialization is the technique of providing an alternative implementation for a template, called the primary template. Partial specialization is an alternative implementation provided for only some of the template parameters. A full specialization is an alternative implementation when arguments are provided for all the template parameters.

Question 5

What are the main disadvantages of using templates?

Answer

The main disadvantages of using templates include the following: complex and cumbersome syntax, compiler errors that are often long and hard to read and understand, and increased compilation times.

Chapter 2, Template Fundamentals

Question 1

What category of types can be used for non-type template parameters?

Answer

Non-type template parameters can only have structural types. Structure types are integral types, floating-point types (as of C++20), enumeration types, pointer types (either to objects or functions), pointer to member types (either to member objects or member functions), lvalue reference types (either to objects or functions), and literal class types that meet several requirements: all base classes are public and non-mutable, all non-static data members are public and non-mutable, and the types of all the base classes and the non-static data members are also structural types or arrays thereof. const and volatile qualified versions of these types are also allowed.

Question 2

Where are default template arguments not allowed?

Answer

Default template arguments cannot be used for parameter packs, in declarations of friend class templates, and in the declaration or definition of an explicit specialization of a function template or member function template.

Question 3

What is explicit instantiation declaration and how does it differ syntactically from explicit instantiation definition?

Answer

Explicit instantiation declaration is the way you can tell the compiler that the definition of a template instantiation is found in a different translation unit and that a new definition should not be generated. The syntax is the same as for explicit instantiation definitions, except that the extern keyword is used in front of the declaration.

Question 4

What is an alias template?

Answer

An alias template is a name that, unlike type aliases, which refer to another type, refers to a template or, in other words, a family of types. Alias templates are introduced with using declarations. They cannot be introduced with typedef declarations.

Question 5

What are template lambdas?

Answer

Template lambdas are an improved form of generic lambdas, introduced in C++20. They allow us to use the template syntax to explicitly specify the shape of the templatized function-call operator of the function object that the compiler is generating for a lambda expression.

Chapter 3, Variadic Templates

Question 1

What are variadic templates and why are they useful?

Answer

Variadic templates are templates with a variable number of arguments. They allow us to write not only functions with variable number of arguments but also class templates, variable templates, and alias templates. Unlike other approaches, such as the use of the va_ macros, they are type-safe, do not require macros, and do not require us to explicitly specify the number of arguments.

Question 2

What is a parameter pack?

Answer

There are two kinds of parameter packs: template parameter packs and function parameter packs. The former are template parameters that accept zero, one, or more template arguments. The latter are function parameters that accept zero, one, or more function arguments.

Question 3

What are the contexts where parameter packs can be expanded?

Answer

Parameter packs can be expanded in a multitude of contexts, as follows: template parameter lists, template argument lists, function parameter lists, function argument lists, parenthesized initializers, brace-enclosed initializers, base specifiers and member initializer lists, fold expressions, using declarations, lambda captures, the sizeof… operator, alignment specifiers, and attribute lists.

Question 4

What are fold expressions?

Answer

A fold expression is an expression involving a parameter pack that folds (or reduces) the elements of the parameter pack over a binary operator.

Question 5

What are the benefits of using fold expressions?

Answer

The benefits of using fold expressions include having less and simpler code to write, fewer template instantiations, which lead to faster compile times, and potentially faster code, since multiple function calls are replaced with a single expression.

Chapter 4, Advanced Template Concepts

Question 1

When is name lookup performed?

Answer

Name lookup is performed at the point of template instantiation for dependent names (those that depend on the type or value of a template parameter) and at the point of template definition for non-dependent names (those that don’t depend on template parameters).

Question 2

What are deduction guides?

Answer

Deduction guides are a mechanism that tells the compiler how to perform class template argument deduction. Deduction guides are fictional function templates representing constructor signatures of a fictional class type. If overload resolution fails on the constructed set of fictional function templates, then the program is ill-formed and an error is generated. Otherwise, the return type of the selected function template specialization becomes the deduced class template specialization.

Question 3

What are forwarding references?

Answer

A forward reference (also known as universal reference) is a reference in a template that behaves as an rvalue reference if an rvalue was passed as an argument or an lvalue reference if an lvalue was passed as an argument. A forwarding reference must have the T&& form such as in template <typename T> void f(T&&). Forms such as T const && or std::vector<T>&& do not represent forwarding references but normal rvalue references.

Question 4

What does decltype do?

Answer

The decltype specifier is a type specifier. It returns the type of an expression. It is usually used in templates together with the auto specifier in order to declare the return type of a function template that depends on its template arguments, or the return type of a function that wraps another function and returns the result from executing the wrapped function.

Question 5

What does std::declval do?

Answer

std::declval is a utility function template from the <utility> header that adds an rvalue reference to its type template argument. It can only be used in unevaluated contexts (compile-time-only contexts that are not evaluated during runtime), and its purpose is to help with dependent type evaluation for types that do not have a default constructor or one that cannot be accessed because it’s private or protected.

Chapter 5, Type Traits and Conditional Compilation

Question 1

What are type traits?

Answer

Type traits are small class templates that enable us to either query properties of types or perform transformations of types.

Question 2

What is SFINAE?

Answer

SFINAE is an acronym for Substitution Failure Is Not An Error. This is a rule for template substitution and works as follows: when the compiler encounters the use of a function template, it substitutes the arguments in order to instantiate the template; if an error occurs at this point, it is not regarded as an ill-formed code, only as a deduction failure. As a result, the function is removed from the overload set instead of causing an error. Therefore, an error only occurs if there is no match in the overload set for a particular function call.

Question 3

What is constexpr if?

Answer

constexpr if is a compile-time version of the if statement. The syntax for it is if constexpr(condition). It’s been available since C++17 and allows us to discard a branch, at compile time, based on the value of a compile-time expression.

Question 4

What does std::is_same do?

Answer

std::is_same is a type trait that checks whether two types are the same. It includes checks for the const and volatile qualifiers, yielding false for two types that have different qualifiers (such as int and int const).

Question 5

What does std::conditional do?

Answer

std::conditional is a metafunction that chooses one type or another based on a compile-time constant.

Chapter 6, Concepts and Constraints

Question 1

What are constraints? What about concepts?

Answer

A constraint is a requirement imposed on a template argument. A concept is a named set of one or more constraints.

Question 2

What is a requires clause and a requires expression?

Answer

A requires clause is a construct that allows us to specify a constraint on a template argument or function declaration. This construct is composed of the requires keyword followed by a compile-time Boolean expression. A requires clause affects the behavior of a function, including it for overload resolution only if the Boolean expression is true. On the other hand, a requires expression has the requires (parameters-list) expression; form, where parameters-list is optional. Its purpose is to verify that some expressions are well-formed, without having any side effects or affecting the behavior of the function. Requires expressions can be used with requires clauses, although named concepts are preferred, mainly for readability.

Question 3

What are the categories of requires expressions?

Answer

There are four categories of requires expressions: simple requirements, type requirements, compound requirements, and nested requirements.

Question 4

How do constraints affect the ordering of templates in overload resolution?

Answer

The constraining of functions affects their order in the overload resolution set. When multiple overloads match the set of arguments, the overload that is more constrained is selected. However, keep in mind that constraining with type traits (or Boolean expressions in general) and concepts is not semantically equal. For details on this topic, revisit the Learning about the ordering of templates with constraints section.

Question 5

What are abbreviated function templates?

Answer

Abbreviated function templates are a new feature introduced in C++20 that provides a simplified syntax for function templates. The auto specifier can be used to define function parameters and the template syntax can be skipped. The compiler will automatically generate a function template from an abbreviated function template. Such functions can be constrained using concepts, therefore imposing requirements on the template arguments.

Chapter 7, Patterns and Idioms

Question 1

What are typical problems for which the Curiously Recuring Template Pattern is used?

Answer

The Curiously Recurring Template Pattern (CRTP) is typically used for solving problems such as adding common functionality to types and avoiding code duplication, limiting the number of times a type can be instantiated, or implementing the composite design pattern.

Question 2

What are mixins and what is their purpose?

Answer

Mixins are small classes that are designed to add functionality to other classes, by inheriting from the classes they are supposed to complement. This is the opposite of the CRTP pattern.

Question 3

What is type erasure?

Answer

Type erasure is the term used to describe a pattern that removes information from types, making it possible for types that are not related to be treated in a generic way. Although forms of type erasure can be achieved with void pointers or polymorphism, the true type erasure pattern is achieved in C++ with templates.

Question 4

What is tag dispatching and what are its alternatives?

Answer

Tag dispatching is a technique that enables us to select one or another function overload at compile time. Although tag dispatching itself is an alternative to std::enable_if and SFINAE, it also has its own alternatives. These are constexpr if in C++17 and concepts in C++20.

Question 5

What are expression templates and where are they used?

Answer

Expression templates are a metaprogramming technique that enables a lazy evaluation of a computation at compile-time. The benefit of this technique is that it avoids performing inefficient operations at runtime at the expense of more complex code that could be difficult to comprehend. Expression templates are typically used to implement linear algebra libraries.

Chapter 8, Ranges and Algorithms

Question 1

What are the sequence containers from the standard library?

Answer

The sequence containers from the C++ standard library are std::vector, std::deque, std::list, std::array, and std::forward_list.

Question 2

What are the common member functions defined in the standard containers?

Answer

The member functions that are defined for most containers in the standard library are size (not present in std::forward_list), empty, clear (not present in std::array, std::stack, std::queue, and std::priority_queue), swap, begin, and end.

Question 3

What are iterators and how many categories exist?

Answer

An iterator is an abstraction that enables us to access the elements of a container in a generic way, without having to know the implementation details of each container. Iterators are key for writing general-purpose algorithms. There are six categories of iterators in C++: input, forward, bidirectional, random-access, contiguous (as of C++17), and output.

Question 4

What operations does a random-access iterator support?

Answer

The random-access iterators must support the following operations (in addition to those required for input, forward, and bidirectional iterators): the + and - arithmetic operators, inequality comparison (with other iterators), compound assignment, and offset dereference operators.

Question 5

What are range access functions?

Answer

Range access functions are non-member functions that provide a uniform way to access the data or properties of containers, arrays, and the std::initializer_list class. These functions include std::size/std::ssize, std::empty, std::data, std::begin, and std::end.

Chapter 9, The Ranges Library

Question 1

What is a range?

Answer

A range is an abstraction for a sequence of elements, defined with a beginning and end iterator. The beginning iterator points to the first element in the sequence. The end iterator points to the one-past-last element of the sequence.

Question 2

What is a view in the ranges library?

Answer

A view in the C++ ranges library, also called a range adaptor, is an object that implements an algorithm that takes one or more ranges as input and perhaps other arguments and returns an adapted range. Views are lazy-evaluated, meaning they do not perform the adaptation until their elements are iterated.

Question 3

What are constrained algorithms?

Answer

Constrained algorithms are implementations of the existing standard library algorithms but in the C++20 ranges library. They are called constrained because their template arguments are constrained using C++20 concepts. In these algorithms, instead of requiring a begin-end pair of iterators for specifying, a range of values accepts a single range argument. However, overloads that accept an iterator-sentinel pair also exist.

Question 4

What is a sentinel?

Answer

A sentinel is an abstraction for an end iterator. This makes it possible for the end iterator to have a different type than the range iterator. Sentinels cannot be dereferenced or incremented. Sentinels are useful when the test for the end of a range depends on some variable (dynamic) condition and you don’t know you are at the end of the range until something happens (for instance, a condition becomes false).

Question 5

How can you check that a sentinel type corresponds to an iterator type?

Answer

You can check that a sentinel type can be used with an iterator type by using the std::sentinel_for concept from the <iterator> header.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset