C++11 Non-Class Types & Templates Guide
C++11 Non-Class Types & Templates Guide
L
Partha Pratim
Das
Programming in Modern C++
E
Objectives &
Outlines
Module M55: C++11 and beyond: Non-class Types and Template Features
T
Non-class Types
enum class
Scope
P
Underlying Type
Forward-Declaration
Partha Pratim Das
N
Integer Types
Generalized unions
Generalized PODs
Department of Computer Science and Engineering
Templates
Indian Institute of Technology, Kharagpur
Extern Templates
Template aliases
Variadic templates
ppd@[Link]
Practice Examples
Local types
Right-angle brackets All url’s in this module have been accessed in September, 2021 and found to be functional
(Nested Template
Closer)
Variable templates
Module Summary
Module M55
L
Partha Pratim
Das
• Explained how these features enhance OOP, generic programming, readability,
E
Objectives &
Outlines type-safety, and performance in C++11
T
Non-class Types
enum class
Scope
P
Underlying Type
Forward-Declaration
N
Integer Types
Generalized unions
Generalized PODs
Templates
Extern Templates
Template aliases
Variadic templates
Practice Examples
Local types
Right-angle brackets
(Nested Template
Closer)
Variable templates
Module Summary
Module M55
L
Partha Pratim
Das
• To familiarize with enum class and fixed width integer
E
Objectives &
Outlines • To familiarize with variadic templates
T
Non-class Types
enum class
Scope
P
Underlying Type
Forward-Declaration
N
Integer Types
Generalized unions
Generalized PODs
Templates
Extern Templates
Template aliases
Variadic templates
Practice Examples
Local types
Right-angle brackets
(Nested Template
Closer)
Variable templates
Module Summary
Module M55
1 Other (non-class) Types
L
Partha Pratim
Das enum class
Scope
E
Objectives &
Outlines
Underlying Type
Forward-Declaration
T
Non-class Types
enum class Integer Types
Scope
P
Underlying Type
Generalized unions
Forward-Declaration
Generalized PODs
N
Integer Types
Generalized unions 2 Templates
Generalized PODs
Templates
Extern Templates
Extern Templates Template aliases
Template aliases
Variadic templates
Variadic templates
Practice Examples Practice Examples
Local types
Right-angle brackets
Local types as template arguments
(Nested Template
Closer) Right-angle brackets (Nested Template Closer)
Variable templates
Variable templates
Module Summary
3 Module Summary
Programming in Modern C++ Partha Pratim Das M55.4
Other (non-class) Types
L
Partha Pratim
Das ◦ enum class, [Link]
◦ An Overview of the New C++ (C++11/14), Scott Meyers Training Courses
E
Objectives &
Outlines
◦ Closer to Perfection: Get to Know C++11 Scoped and Based Enum Types
◦ enum to string in modern C++11 / C++14 / C++17 and future C++20, [Link]
T
Non-class Types
enum class
• Integer Types
Scope ◦ Fixed width integer types, [Link]
P
Underlying Type ◦ long long – a longer integer, [Link]
Forward-Declaration ◦ Extended integer types, [Link]
•
N
Integer Types
Generalized unions
Generalized unions
Generalized PODs ◦ Generalized unions, [Link]
Templates • Generalized PODs
Extern Templates ◦ Generalized PODs, [Link]
Template aliases
Variadic templates
Practice Examples
Local types
Other (non-class) Types
Right-angle brackets
(Nested Template
Closer)
Variable templates
Module Summary
Module M55
• There have been several additions to non-class types in C++11. They include:
L
Partha Pratim
Das
◦ enum class: These solve several problems for enum in C++03
E
Objectives &
Outlines ◦ Integer Types: These include:
T
Non-class Types . Fixed width integer types (as enhancements to integer types with size that is
enum class
Scope standard-defined). This comes from C99 feature
P
Underlying Type
Forward-Declaration
. long long – a longer integer of 64 bits
. Extended precision in integer types
N
Integer Types
Generalized unions
Generalized PODs ◦ Generalized unions: That allows rules for using union members with ctor / dtor /
Templates copy ops as enhancement over C++03
Extern Templates
Template aliases ◦ Generalized PODs: That defines rules for enhanced PODs in C++11
Variadic templates
Practice Examples • Important features to learn
Local types
Right-angle brackets
◦ enum class
(Nested Template
Closer) ◦ Fixed width integer, and
Variable templates
◦ long long
Module Summary
Module M55 • enum classes (also called: new enums, strong enums, scoped enums) address 3 problems with
C++03 enumerations:
L
Partha Pratim
Das
◦ C++03 enums implicitly convert to an integer, causing errors when someone does not want
E
Objectives &
Outlines
an enumeration to act as an integer
◦ C++03 enums export their enumerators to the surrounding scope, causing name clashes
T
Non-class Types
enum class ◦ The underlying type of an enum cannot be specified in C++03, causing confusion,
Scope
compatibility problems, and makes forward declaration impossible
P
Underlying Type
Forward-Declaration • enum classes (strong enum) are strongly typed and scoped:
N
Integer Types
Generalized unions
Generalized PODs
enum Alert { green, yellow, orange, red }; // C++03 enum
enum class Color { red, blue }; // scoped and strongly typed enum
Templates
// no export of enumerator names into enclosing scope
Extern Templates
// no implicit conversion to int
Template aliases
Variadic templates
enum class TrafficLight { red, yellow, green };
Practice Examples
Alert a = 7; // error (as ever in C++03)
Local types Color c = 7; // error: no int->Color conversion
Right-angle brackets int a2 = red; // okay: Alert->int conversion
(Nested Template int a3 = Alert::red; // error in C++03; okay in C++11
Closer)
Variable templates
int a4 = blue; // error: blue not in scope
int a5 = Color::blue; // error: not Color->int conversion
Module Summary
Color a6 = Color::blue; // okay
Programming in Modern C++ Partha Pratim Das M55.7
enum class: Scopes
L
Partha Pratim
Das enum Color { Bronze, Silver, Gold };
enum Bullion { Silver, Gold };
E
Objectives & enum Metal { Silver, Gold, Platinum };
Outlines
enum CreditCard { Silver, Gold, Platinum };
T
Non-class Types
enum class
Scope • Silver and Gold clash in names between Color, Bullion, Metal and CreditCard. In
P
Underlying Type
C++11, we can use scoped enum:
Forward-Declaration
N
Integer Types
Generalized unions enum class Color { Bronze, Silver, Gold };
Generalized PODs enum class Bullion { Silver, Gold };
enum class Metal { Silver, Gold, Platinum };
Templates
Extern Templates
enum class CreditCard { Silver, Gold, Platinum };
Template aliases
Variadic templates
Practice Examples
• No clash of names as enumerators of a scoped enum use a qualified name with enclosing scope:
Local types
Right-angle brackets Color col1 = Bronze; // error, Bronze not in scope
(Nested Template
Closer)
Variable templates
Color col2 = Color::Bronze; // OKay
if ((col2 == Color::Silver) || (col2 == Color::Gold)) // OKay
Module Summary
//...
Programming in Modern C++ Partha Pratim Das M55.8
enum class: Underlying Type
Module M55
• Specification of underlying type (optional) now permitted provided every value fits the type:
enum Color: unsigned int { red, green, blue };
L
Partha Pratim
Das
enum Weather: std::uint8_t { sunny, rainy, cloudy, foggy };
E
Objectives &
Outlines enum Status: std::uint8_t { pending, ready, unknown = 9999 }; // error! unknown does not fit size
T
Non-class Types
enum Color { red, green, blue }; // okay -- type specification is optional as in C++03
enum class
Scope • Strongly typed enums:
P
Underlying Type
Forward-Declaration
◦ No implicit conversion to int
. No comparing scoped enums values with ints
N
Integer Types
Generalized unions
Generalized PODs
. No comparing scoped enums objects of different types.
Templates
. Explicit cast to int (or types convertible from int) okay
Extern Templates ◦ Values scoped to enum type
Template aliases ◦ Underlying type defaults to int
Variadic templates
enum class Elevation: char { low, high }; // underlying type = char
Practice Examples
Local types
enum class Voltage { low, high }; // underlying type = int
Right-angle brackets
Elevation e = low; // error! no low in scope
(Nested Template Elevation e = Elevation::low; // okay
Closer)
int x = Voltage::high; // error! no conversion to int
Variable templates
if (e) ... // error! no conversion to bool
Module Summary if (e == Voltage::high) ... // error! no conversion from Elevation to Voltage
Programming in Modern C++ Partha Pratim Das M55.9
enum class: Forward-Declaration
Module M55
L
Partha Pratim
Das
enum Color; // as in C++03, error!: size unknown
E
Objectives & enum Weather: std::uint8_t; // okay
Outlines
enum class Elevation; // okay, underlying type implicitly int
T
Non-class Types
double atmosphericPressure(Elevation e); // okay
enum class
Scope
P
Underlying Type
Forward-Declaration
N
Integer Types
Generalized unions
Generalized PODs
Templates
Extern Templates
Template aliases
Variadic templates
Practice Examples
Local types
Right-angle brackets
(Nested Template
Closer)
Variable templates
Module Summary
L
Partha Pratim
Das
◦ sizeof(char), sizeof(short), sizeof(int), etc.: unspecified
E
Objectives &
Outlines
◦ The following order is only guaranteed:
sizeof(unsigned char) <= sizeof(char) <= sizeof(short) <=
T
Non-class Types
enum class sizeof(int) <= sizeof(long)
Scope
P
Underlying Type • C++11 provides fixed width integer types in <cstdint> for N = { 8, 16, 32, 64 }:
Forward-Declaration
◦ int<N> t (uint<N> t): For example, int8 t (uint8 t)
N
Integer Types
Generalized unions . signed (unsigned) integer type with width of exactly N bits with no padding bits
Generalized PODs
Templates
. signed integer type to use 2’s complement for negative values
Extern Templates ◦ int fast<N> t (uint fast<N> t): For example, int fast8 t (uint fast8 t)
Template aliases
Variadic templates . fastest signed (unsigned) integer type with width of at least N bits
Practice Examples
Local types
◦ int least<N> t (uint least<N> t): For example, int least8 t (uint least8 t)
Right-angle brackets
(Nested Template
. smallest signed (unsigned) integer type with width of at least N bits
Closer)
Variable templates ◦ intmax t (uintmax t):
Module Summary . maximum-width signed (unsigned) integer type
Programming in Modern C++ Partha Pratim Das M55.11
Extended Size & Precision of integers
Module M55
• What is the difference between the int types: int8 t, int least8 t, and int fast8 t?
L
Partha Pratim
Das
◦ Suppose we have a C compiler for a 36-bit system, with sizeof(char) = 9 bits,
E
Objectives &
Outlines
sizeof(short) = 18 bits, sizeof(int) = 36 bits, and sizeof(long) = 72 bits. Then
. int8 t does not exist, because there is no way to satisfy the constraint of having
T
Non-class Types
enum class exactly 8 value bits with no padding
Scope
P
Underlying Type . int least8 t is a typedef of char. NOT of short or int, because the standard
Forward-Declaration
requires the smallest type with at least 8 bits
N
Integer Types
Generalized unions . int fast8 t can be anything. It is likely to be a typedef of int if the native size is
Generalized PODs
considered to be fast
Templates
Extern Templates
• C++11 provides support for long long – a longer integer
Template aliases
Variadic templates
◦ An integer that’s at least 64 bits long. For example:
Practice Examples long long x = 9223372036854775807LL;
Local types
Right-angle brackets
◦ No, there are no long long longs nor can long be spelled short long long
(Nested Template
Closer) • C++11 provides support for extended integer (precision) types with a set of rules
Variable templates
Module Summary
Module M55 • In C++03, a member with a user-defined ctor, dtor, or assignment cannot be a member of a union:
union U {
L
Partha Pratim
Das
int m1;
complex<double> m2; // error (silly): complex has constructor
E
Objectives & string m3; // error (not silly): string has an invariant maintained by ctor, copy, & dtor
Outlines };
•
T
Non-class Types Obviously, it is illegal to write one member and then read another
enum class
Scope
U u; // which constructor, if any?
P
Underlying Type
u.m1 = 1; // assign to int member
Forward-Declaration
string s = u.m3; // disaster: read from string member
•
N
Integer Types
C++11 allows a member of types with ctor and dtor. It also adds a restriction to make the more
Generalized unions
Generalized PODs
flexible unions less error-prone by encouraging the building of discriminated unions
Templates
• Union member types are restricted:
Extern Templates ◦ No virtual functions, No references, and No bases (as ever)
Template aliases ◦ If a union has a member with a user-defined ctor, copy, or dtor then that special function is deleted;
Variadic templates
Practice Examples
that is, it cannot be used for an object of the union type. This is new. For example:
Local types union U1 { union U2 {
Right-angle brackets int m1; int m1;
(Nested Template
Closer)
complex<double> m2; // okay string m3; // okay
Variable templates }; };
Module Summary ◦ This may look error-prone, but the new restriction helps
Programming in Modern C++ Partha Pratim Das M55.13
Generalized unions
Module M55
• Consider:
U1 u; // okay
L
Partha Pratim u.m2 = { 1, 2 }; // okay: assign to the complex member
Das
U2 u2; // error: the string destructor caused the U2 destructor to be deleted
U2 u3 = u2; // error: the string copy constructor caused the U2 copy constructor to be deleted
E
Objectives &
Outlines • Basically, U2 is useless unless it is in a discriminated unions, such as:
T
Non-class Types class Widget { private: // Three alternative implementations represented as a union
enum class enum class Tag { point, number, text } type; // discriminant
Scope
union { point p; /* point has constructor */ int i;
P
Underlying Type
string s; // string has default ctor, copy operations, and dtor
Forward-Declaration
}; // ...
N
Integer Types
Generalized unions widget& operator=(const widget& w) { // necessary because of the string variant
Generalized PODs if (type==Tag::text && [Link]==Tag::text) { s = w.s; // usual string assignment
return *this;
Templates
}
Extern Templates
Template aliases
if (type==Tag::text) s.~string(); // destroy (explicitly!)
Variadic templates
switch ([Link]) {
Practice Examples case Tag::point: p = w.p; break; // normal copy
Local types case Tag::number: i = w.i; break;
Right-angle brackets case Tag::text: new(&s)(w.s); break; // placement new
(Nested Template
Closer)
}
Variable templates type = [Link]; return *this;
}
Module Summary
};
Programming in Modern C++ Partha Pratim Das M55.14
Generalized PODs
Module M55
• A POD (Plain Old Data) is something that can be manipulated like a C struct, for example, bitwise
copyable with memcpy(), bitwise initializable with memset(), etc.
L
Partha Pratim
Das
• In C++03 a POD is decided by a set of restrictions on the features used in the definition of a struct:
E
Objectives &
Outlines struct S { int a; }; // Is a POD
struct SS { int a; SS(int aa): a(abs(aa)) { assert(a>=0); } }; // Not a POD in C++03; a POD in C++11
T
Non-class Types
enum class struct SSS { virtual void f(); /* ... */ }; // Definitely not POD
Scope
P
Underlying Type
Forward-Declaration
• In C++11, S and SS are standard layout types (a superset of POD types) where the ctor does not affect
the layout (so memcpy() would be fine), only the initialization rules do (memset() would be bad)
N
Integer Types
Generalized unions • However, SSS will still have the vptr and will not be anything like plain old data. C++11 defines:
Generalized PODs
◦ POD Types: Check by is pod<T>::value of type bool (deprecated in C++20)
Templates
Extern Templates
◦ Trivially Copyable Types: Check by is trivially copyable<T>::value of type bool
Template aliases ◦ Trivial Types: Check by is trivial<T>::value of type bool, and
Variadic templates ◦ Standard-Layout Types: Check by is standard layout<T>::value of type bool
Practice Examples
Local types
to deal with various technical aspects of what used to be PODs. POD is defined recursively:
Right-angle brackets
(Nested Template
◦ If all members and bases are PODs, then it is a POD
Closer) ◦ Naturally: No virtual functions, No virtual bases, No references, and No multiple access specifiers
Variable templates
• In C++11, PODs is that adding or subtracting constructors do not affect layout or performance
Module Summary
L
Partha Pratim
Das ◦ Extern templates, [Link]
• Template aliases
E
Objectives &
Outlines ◦ Template aliases; Type alias, alias template (since C++11), [Link]
◦ Type alias, alias template (since C++11)
T
Non-class Types
enum class
◦ Alias Templates and Template Parameters, 2021
Scope • Variadic templates
P
Underlying Type ◦ Variadic templates, [Link]
Forward-Declaration ◦ Variadic templates in C++, Eli Bendersky, 2014
N
Integer Types
Generalized unions
• Local types as template arguments
Generalized PODs ◦ Local types as template arguments, [Link]
Templates • Right-angle brackets (Nested Template Closer)
Extern Templates ◦ Right-angle brackets, [Link]
Template aliases
Variadic templates
• Variable templates (C++14)
Practice Examples ◦ Variable templates, [Link]
Local types
Right-angle brackets
(Nested Template
Templates
Closer)
Variable templates
Module Summary
Module M55
L
Partha Pratim
Das
◦ Extern templates: Used to suppress multiple instantiations
E
Objectives &
Outlines ◦ Template aliases: Used to make a template just like another template
◦ Variadic templates: These are templates with variable number of parameters that
T
Non-class Types
enum class
Scope
are useful in various contexts like writing a type-safe printf or defining a tuple
P
Underlying Type ◦ Local types as template arguments: Uses for local as well as unnamed types as
Forward-Declaration
template arguments
N
Integer Types
Generalized unions
Generalized PODs
◦ Right-angle brackets (Nested Template Closer): Fixes ”>>” issue of C++03 for
Templates nested templates
Extern Templates
◦ Variable templates (C++14): Variables can now be directly templatized
Template aliases
Variadic templates • Important features to learn:
Practice Examples
Local types ◦ Variadic templates, and
Right-angle brackets
(Nested Template
Closer)
◦ Nested template closer
Variable templates
Module Summary
Module M55
• A template specialization can be explicitly declared as a way to suppress multiple
instantiations. For example:
L
Partha Pratim
Das
E
Objectives & #include "MyVector.h"
Outlines
T
Non-class Types
enum class
// Suppresses implicit instantiation below --
Scope // MyVector<int> will be explicitly instantiated elsewhere
P
Underlying Type extern template class MyVector<int>;
Forward-Declaration
N
Integer Types
Generalized unions void foo(MyVector<int>& v) {
Generalized PODs // use the vector in here
Templates }
Extern Templates
Template aliases
• The elsewhere might look something like this:
Variadic templates
Practice Examples
Local types
#include "MyVector.h"
Right-angle brackets template class MyVector<int>; // Make MyVector available to clients
(Nested Template
Closer)
// For example, of the shared library
Variable templates
• This is basically a way of avoiding significant redundant work by the compiler and linker
Module Summary
Module M55
• We can make a template like another template with a few of template arguments bound:
L
Partha Pratim template<class T>
Das
using Vec = std::vector<T, My_alloc<T>>; // standard vector using my allocator
E
Objectives & Vec<int> fib = { 1, 2, 3, 5, 8, 13 }; // allocates elements using My_alloc
Outlines
vector<int, My_alloc<int>> verbose = fib; // verbose and fib are of the same type
T
Non-class Types
enum class • using is used to get a linear notation where name is followed by what it refers to. Also, we can
Scope
alias a set of specializations but we cannot specialize an alias:
P
Underlying Type
Forward-Declaration // int_exact_trait<N>::type is a type with exactly N bits
template<int> struct int_exact_traits { typedef int type; };
N
Integer Types
Generalized unions
Generalized PODs
template<> struct int_exact_traits<8> { typedef char type; };
template<> struct int_exact_traits<16> { typedef char[2] type; };
Templates
Extern Templates
// ... define alias for convenient notation
Template aliases template<int N> using int_exact = typename int_exact_traits<N>::type;
Variadic templates int_exact<8> a = 7; // int_exact<8> is an int with 8 bits
Practice Examples
Local types • Type aliases can also be used as a different syntax for ordinary type aliases:
Right-angle brackets
(Nested Template typedef void (*PFD)(double); // C style
Closer)
using PF = void (*)(double); // using plus C-style type
Variable templates
using P = auto (*)(double) -> void; // using plus suffix return type
Module Summary
Module M55
• Consider template class Matrix:
L
Partha Pratim template <typename T, int Line, int Col>
Das
class Matrix { ... };
E
Objectives &
Outlines • Matrix has 3 parameters. The type parameter T, and the non-type parameters Line, and Col
• For readability, we want to have two special matrices: a Square and a Vector. A Square’s
T
Non-class Types
enum class number of lines and columns should be equal. A Vector’s line size should be one.
Scope
P
Underlying Type template <typename T, int Line>
Forward-Declaration using Square = Matrix<T, Line, Line>; // #1
N
Integer Types
Generalized unions
Generalized PODs
template <typename T, int Line>
Templates
using Vector = Matrix<T, Line, 1>; // #2
Extern Templates • using declares a type alias (#1 & #2). While the primary template Matrix can be
Template aliases
Variadic templates parametrized in the three dimensions T, Line, and Col, the type aliases Square and Vector
Practice Examples reduce the parametrization to the two dimensions T and Line
Local types
Right-angle brackets • Template alias creates names for partially bound templates. Using Square and Vector is easy:
(Nested Template
Closer) Matrix<int, 5, 3> ma;
Variable templates Square<double, 4> sq; // Matrix<double, 4, 4>
Module Summary Vector<char, 5> vec; // Matrix<char, 5, 1>
Programming in Modern C++ Partha Pratim Das M55.20
Variadic templates: printf
Module M55 • Let us start by implementing printf – the most well-known variadic function. Consider:
const char* pi = "pi";
L
Partha Pratim const char* m = "The value of %s is about %g (unless you live in %s)\n";
Das
printf(m, pi, 3.14159, "Indiana"); // int printf(const char *format, ...) in C
•
E
Objectives & The simplest case of printf() is when there are no arguments except the format string:
Outlines
void printf(const char* s) {
T
Non-class Types while (s && *s) {
enum class if (*s==’%’ && *++s!=’%’) // make sure that there was not meant to be more args (%% for %)
Scope
P
throw std::runtime_error("invalid format: missing arguments"); // from <exception>
Underlying Type
std::cout << *s++;
Forward-Declaration
}
N
Integer Types
Generalized unions
}
Generalized PODs • That done, we must handle printf() with more arguments (recursive):
Templates template<typename T, typename... Args> // note the "..."
Extern Templates void printf(const char* s, T value, Args... args) { // recursive function. note the "..."
Template aliases while (s && *s) {
Variadic templates if (*s==’%’ && *++s!=’%’) { // a format specifier (ignore which one it is)
Practice Examples std::cout << value; // use first non-format argument
Local types
return printf(++s, args...); // "peel off" first argument: recursive call
Right-angle brackets
(Nested Template
}
Closer) std::cout << *s++;
Variable templates }
Module Summary throw std::runtime_error("extra arguments provided to printf");
}
Programming in Modern C++ Partha Pratim Das M55.21
Variadic templates: printf
Module M55
• The code peels off the first non-format arg. and then calls itself recursively. When there is no
more non-format arg., it calls the first printf() – functional programming at compile time
L
Partha Pratim
Das
• The Args... defines what is called a parameter pack – a sequence of (type/value) pairs to
E
Objectives &
Outlines
peel off arguments starting with the first:
◦ When printf() is called with one argument, the first printf(const char*) is chosen
T
Non-class Types
enum class
Scope
◦ When printf() is called with two or more arguments, the second printf(const char*
P
Underlying Type s, T value, Args... args) is chosen, with the first argument as s, the second as
Forward-Declaration
value, and the rest (if any) bundled into the parameter pack args for later use
N
Integer Types
Generalized unions ◦ In the call printf(++s, args...) the parameter pack args is expanded so that the next
Generalized PODs
argument can now be selected as value
Templates
Extern Templates
◦ This carries on until args is empty so that the first printf() is called
Template aliases • For generic functional programming, we declare and use a simple variadic template function:
Variadic templates
template<class ... Types>
Practice Examples
Local types
void f(Types ... args); // variadic template function. That is, a function that can take
Right-angle brackets
// an arbitrary number of arguments of arbitrary types
(Nested Template f(); // OK: args contains no arguments
Closer)
f(1); // OK: args contains one argument: int
Variable templates
f(2, 1.0); // OK: args contains two arguments: int and double
Module Summary
Module M55 • Let us implement a function that adds all of its arguments together:
template<typename T> T adder(T v) { cout << __PRETTY_FUNCTION__ << endl; return v; }
L
Partha Pratim
Das
template<typename T, typename... Args> // template parameter pack: typename... Args
E
Objectives & T adder(T first, Args... args) // function parameter pack: Args... args
Outlines { cout << __PRETTY_FUNCTION__ << endl; return first + adder(args...); }
•
T
Non-class Types And we could call and trace it as: long sum = adder(1, 2, 3, 8, 7); // 21
enum class
Scope
T adder(T, Args ...) [with T = int; Args = int, int, int, int] // __PRETTY_FUNCTION__ is a trace
P
Underlying Type
T adder(T, Args ...) [with T = int; Args = int, int, int] // expansion macro in gcc
Forward-Declaration
T adder(T, Args ...) [with T = int; Args = int, int]
T adder(T, Args ...) [with T = int; Args = int]
N
Integer Types
Generalized unions T adder(T) [with T = int]
Generalized PODs
• We could also call as:
Templates
std::string s1 = "x", s2 = "aa", s3 = "bb", s4 = "yy";
Extern Templates
std::string ssum = adder(s1, s2, s3, s4); // "x"+"aa"+"bb"+"yy" = "xaabbyy"
Template aliases
Variadic templates • adder will accept any number of arguments, and will compile properly as long as it can apply the
Practice Examples
operator+ to them following template and overload resolution rules
Local types
Right-angle brackets
• Variadic templates are like recursive code with a base case (adder(T v)) and a general case which
(Nested Template
Closer)
recurses as in adder(args...)
Variable templates • In adder - the first argument is peeled off the template parameter pack into type T (argument first). So
Module Summary with each call, the parameter pack shortens by one parameter to hit the base case
Programming in Modern C++ Partha Pratim Das M55.23
Variadic templates: Example: power square
Module M55
• Let us consider another function for practice:
L
Partha Pratim #include <iostream>
Das
E
Objectives &
Outlines template <typename T> // Our base case just returns the value
double power_sum(T t) { cout << __PRETTY_FUNCTION__ << endl; return t; }
T
Non-class Types
template <typename T, typename... Rest> // Our new recursive case
enum class
Scope
double power_sum(T t, Rest... rest) { cout << __PRETTY_FUNCTION__ << endl;
P
Underlying Type
return t + power_sum(square(rest)...);
Forward-Declaration }
int main() {
N
Integer Types
Generalized unions int result = power_sum(2, 4, 6);
Generalized PODs // 2 + power_sum(square(rest)...);
Templates // 2 + power_sum(square(4), square(6));
Extern Templates
// 2 + (square(4) + power_sum(square(rest)...))
Template aliases // 2 + (square(4) + power_sum(square(square(6)));
Variadic templates // 2 + (square(4) + (square(square(6))))
Practice Examples std::cout << result;
Local types }
Right-angle brackets double power_sum(T, Rest ...) [with T = int; Rest = int, int]
(Nested Template
Closer) double power_sum(T, Rest ...) [with T = int; Rest = int]
Variable templates double power_sum(T) [with T = int]
Module Summary
1314
Module M55
• Consider:
L
Partha Pratim #include <iostream>
Das
template<typename... Types> // declare list struct
struct Count; // walking template. Putting { } is optional
E
Objectives &
Outlines
template<> struct Count<> { // recognize end of list
T
Non-class Types
const static int value = 0;
enum class
Scope
};
P
Underlying Type
Forward-Declaration template<typename T, typename... Rest> // walk list
struct Count<T, Rest...> {
N
Integer Types
Generalized unions const static int value = 1 + Count<Rest...>::value;
Generalized PODs };
Templates
Extern Templates
int main() {
Template aliases auto count1 = Count<int, double, char>::value; // count1 = 3
Variadic templates auto count2 = Count<int>::value; // count2 = 1
Practice Examples auto count3 = Count<>::value; // count3 = 0
Local types std::cout << count1 << std::endl;
Right-angle brackets std::cout << count2 << std::endl;
(Nested Template
Closer) std::cout << count3 << std::endl;
Variable templates }
Module Summary • A simple way to count the number of arguments
Programming in Modern C++ Partha Pratim Das M55.25
Local types as template arguments
Module M55 • In C++03, local and unnamed types could not be used as template arguments. C++11 relaxes:
void f(vector<X>& v) {
L
Partha Pratim
Das
struct Less { bool operator()(const X& a, const X& b) { return a.v<b.v; } };
sort([Link](), [Link](), Less()); // C++03: error: Less is local
E
Objectives & // C++11: okay
Outlines }
•
T
Non-class Types In C++11, we also have the alternative of using a lambda expression:
enum class
Scope
void f(vector<X>& v) {
P
Underlying Type
sort([Link](), [Link](), [] (const X& a, const X& b) return a.v < b.v; ); // C++11
Forward-Declaration
}
•
N
Integer Types
It is worth remembering that naming action can be quite useful for documentation and an
Generalized unions
Generalized PODs
encouragement to good design. Also, non-local (necessarily named) entities can be reused.
Templates
• C++11 also allows values of unnamed types to be used as template arguments:
Extern Templates
Template aliases template<typename T> void foo(T const& t) { }
Variadic templates enum X { x };
Practice Examples enum { y };
Local types int main() {
Right-angle brackets foo(x); // C++03: okay; C++11: okay
(Nested Template
Closer) foo(y); // C++03: error; C++11: okay
Variable templates enum Z { z };
Module Summary foo(z); // C++03: error; C++11: okay
}
Programming in Modern C++ Partha Pratim Das M55.26
“>>” as Nested Template Closer
Module M55
• >> now closes a nested template when possible:
L
Partha Pratim
Das
std::vector<std::list<int>> vi1; // fine in C++11, error in C++03
E
Objectives &
Outlines
• The C++03 extra space approach remains valid:
T
Non-class Types
enum class
Scope
P
std::vector<std::list<int> > vi2; // fine in C++11 and C++03
Underlying Type
Forward-Declaration
N
Integer Types
Generalized unions • For a shift operation, use parentheses:
Generalized PODs
◦ That is, “>>” now treated like “>” during template parsing:
Templates
Extern Templates
Template aliases constexpr int n = ... ; // n, m are compile-
Variadic templates
constexpr int m = ... ; // time constants
Practice Examples
Local types
constexpr std::list<std::array<int, n >> 2 >> L1; // error in C++03: 2 shifts
Right-angle brackets // error in C++11: 1st ">>"
(Nested Template
Closer) // closes both templates
Variable templates std::list<std::array<int, (n>>2) >> L2; // fine in C++11,
Module Summary // error in C++03 (2 shifts)
Programming in Modern C++ Partha Pratim Das M55.27
Variable templates (C++14)
Module M55
• A variable template may be introduced by a template declaration at namespace scope, where
L
Partha Pratim
Das
declaration declares a variable
#include <iostream>
E
Objectives &
Outlines template<typename T> T n = T(5); // variable template with default value: C++14
T
Non-class Types
enum class int main() { n<int> = 10; // instantiating variable template
Scope std::cout << n<int> << " "; // instantiated value: 10
P
Underlying Type std::cout << n<double> << " "; // default value: 5
Forward-Declaration
}
N
Integer Types
Generalized unions • It can be constant too:
Generalized PODs
#include <iostream>
Templates // variable template with constanr value
Extern Templates // math constant with precision dictated by actual type
Template aliases template<typename T> constexpr T pi = T(3.14159265358979323846); // C++14
Variadic templates
auto area_of_circle_with_radius = [](auto r) { return pi<decltype(r)> * r * r; }; // C++14
Practice Examples
// template<class T> T area_of_circle_with_radius(T r) { return pi<T> * r * r; } // C++11
Local types
Right-angle brackets
(Nested Template int main() { double r1 = 2.0; int r2 = 2;
Closer)
std::cout << area_of_circle_with_radius(r1) << std::endl; // for double: 12.5664
Variable templates
std::cout << area_of_circle_with_radius(r2) << std::endl; // for int: 12
Module Summary }
Programming in Modern C++ Partha Pratim Das M55.28
Module Summary
Module M55
• Introduced several features in C++11 for non-class types and templates with examples
L
Partha Pratim
Das
• Familiarized with important non-class types like enum class and fixed width integer
E
Objectives &
Outlines • Familiarized with important templates like variadic templates
T
Non-class Types
enum class
Scope
P
Underlying Type
Forward-Declaration
N
Integer Types
Generalized unions
Generalized PODs
Templates
Extern Templates
Template aliases
Variadic templates
Practice Examples
Local types
Right-angle brackets
(Nested Template
Closer)
Variable templates
Module Summary