The C++ Programming Language, 4th Edition

This book aims for completeness. Here is described every language feature and standard-library component that a professional programmer is likely to need.


Bjarne Stroustrup


1366 Pages

134554 Reads

12 Downloads

English

PDF Format

18.7 MB

C, C++ Programming

Download PDF format


  • Bjarne Stroustrup    
  • 1366 Pages   
  • 03 Mar 2015
  • Page - 1

    read more..

  • Page - 2

    The C++ Programming Language Fourth Edition Bjarne Stroustrup Upper Saddle River, NJ • Boston • Indianapolis • San Francisco New York • Totonto • Montreal • London • Munich • Paris • Madrid Capetown • Sydney • Tokyo • Singapore • Mexico City read more..

  • Page - 3

    Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and the publisher was aware of a trademark claim, the designations have been printed with initial capital letters or in all capitals. The author and publisher have taken care in the preparation of this book, but make read more..

  • Page - 4

    Contents Contents iii Preface v Preface to the Fourth Edition ...................................................... v Preface to the Third Edition ........................................................ ix Preface to the Second Edition ..................................................... xi Preface to the First Edition ......................................................... xii Part I: Introductory Material 1. Notes to read more..

  • Page - 5

    iv Contents 11. Select Operations ........................................................................ 273 12. Functions ..................................................................................... 305 13. Exception Handling .................................................................... 343 14. Namespaces ................................................................................. 389 15. Source Files and Programs read more..

  • Page - 6

    Preface All problems in computer science can be solved by another level of indirection, except for the problem of too many layers of indirection. – David J. Wheeler C++ feels like a new language. That is, I can express my ideas more clearly, more simply, and more directly in C++11 than I could in C++98. Furthermore, the resulting programs are better checked by the read more..

  • Page - 7

    vi Preface techniques for writing quality code. C++ is a language for someone who takes the task of program- ming seriously. Our civilization depends critically on software; it had better be quality software. There are billions of lines of C++ deployed. This puts a premium on stability, so 1985 and 1995 C++ code still works and will continue to work for decades. However, read more..

  • Page - 8

    vii Acknowledgments In addition to the people mentioned in the acknowledgment sections of the previous editions, I would like to thank Pete Becker, Hans-J. Boehm, Marshall Clow, Jonathan Coe, Lawrence Crowl, Walter Daugherty, J. Daniel Garcia, Robert Harle, Greg Hickman, Howard Hinnant, Brian Kernighan, Daniel Krügler, Nevin Liber, Michel Michaud, Gary Powell, Jan Christiaan van Winkel, read more..

  • Page - 9

    This page intentionally left blank read more..

  • Page - 10

    Preface to the Third Edition Programming is understanding. – Kristen Nygaard I find using C++ more enjoyable than ever. C++’s support for design and programming has improved dramatically over the years, and lots of new helpful techniques have been developed for its use. However, C++ is not just fun. Ordinary practical programmers have achieved significant improvements in read more..

  • Page - 11

    x Preface to the Third Edition That is, the focus is on the language as the tool for design and programming rather than on the lan- guage in itself. This book demonstrates key techniques that make C++ effective and teaches the fundamental concepts necessary for mastery. Except where illustrating technicalities, examples are taken from the domain of systems software. A read more..

  • Page - 12

    Preface to the Second Edition The road goes ever on and on. – Bilbo Baggins As promised in the first edition of this book, C++ has been evolving to meet the needs of its users. This evolution has been guided by the experience of users of widely varying backgrounds working in a great range of application areas. The C++ user-community has grown a hundredfold during the read more..

  • Page - 13

    xii Preface to the Second Edition of the useful classes presented here, such as linked lists, arrays, character strings, matrices, graphics classes, associative arrays, etc., are available in ‘‘bulletproof ’’ and/or ‘‘goldplated’’ versions from a wide variety of commercial and non-commercial sources. Many of these ‘‘industrial strength’’ classes and libraries are actually read more..

  • Page - 14

    Preface to the First Edition Language shapes the way we think, and determines what we can think about. – B.L.Whorf C++ is a general purpose programming language designed to make programming more enjoyable for the serious programmer. Except for minor details, C++ is a superset of the C programming lan- guage. In addition to the facilities provided by C, C++ provides flexible read more..

  • Page - 15

    xiv Preface to the First Edition Acknowledgments C++ could never hav e matured without the constant use, suggestions, and constructive criticism of many friends and colleagues. In particular, Tom Cargill, Jim Coplien, Stu Feldman, Sandy Fraser, Steve Johnson, Brian Kernighan, Bart Locanthi, Doug McIlroy, Dennis Ritchie, Larry Rosler, Jerry Schwarz, and Jon Shopiro provided important read more..

  • Page - 16

    Part I Introduction This introduction gives an overview of the major concepts and features of the C++ pro- gramming language and its standard library. It also provides an overview of this book and explains the approach taken to the description of the language facilities and their use. In addition, the introductory chapters present some background information about C++, the design of read more..

  • Page - 17

    2 Introduction Part I ‘‘... and you, Marcus, you have giv en me many things; now I shall give you this good advice. Be many people. Give up the game of being always Marcus Cocoza. You have worried too much about Marcus Cocoza, so that you have been really his slave and prisoner. You have not done anything without first considering how it would affect read more..

  • Page - 18

    1 Notes to the Reader Hurry Slowly (festina lente). – Octavius, Caesar Augustus • The Structure of This Book Introduction; Basic Facilities; Abstraction Mechanisms; The Standard Library; Examples and References • The Design of C++ Programming Styles; Type Checking; C Compatibility; Language, Libraries, and Systems • Learning C++ Programming in C++; Suggestions for C++ Programmers; Suggestions read more..

  • Page - 19

    4 Notes to the Reader Chapter 1 Making parts of the book relatively self-contained implies some repetition, but repetition also serves as review for people reading the book linearly. The book is heavily cross-referenced both to itself and to the ISO C++ standard. Experienced programmers can read the (relatively) quick ‘‘tour’’ of C++ to gain the overview needed to use the read more..

  • Page - 20

    Section 1.1.2 Basic Facilities 5 Chapter 7 Pointers, Arrays, and References Chapter 8 Structures, Unions, and Enumerations Chapter 9 Statements: Declarations as statements, selection statements (if and switch ), itera- tion statements (for, while , and do ), goto , and comments Chapter 10 Expressions: A desk calculator example, survey of operators, constant expres- sions, and implicit type read more..

  • Page - 21

    6 Notes to the Reader Chapter 1 Classes can be organized into hierarchies: Chapter 20 Derived Classes presents the basic language facilities for building hierarchies out of classes and the fundamental ways of using them. We can provide complete separation between an interface (an abstract class) and its implementations (derived classes); the connection between them is provided by read more..

  • Page - 22

    Section 1.1.4 The Standard Library 7 Chapter 32 STL Algorithms presents the algorithms from the STL, including nd() , sort() , and merge() . Chapter 33 STL Iterators presents iterators and other utilities from the STL, including reverse_iterator , move_iterator , and function . Chapter 34 Memory and Resources presents utility components related to memory and resource management, such as array read more..

  • Page - 23

    8 Notes to the Reader Chapter 1 programming language are really like. This book concentrates on the language features and the standard-library facilities. These are the basic techniques from which every program is composed. The rules and techniques for such composition are emphasized. The selection of examples reflects my background in compilers, foundation libraries, and simu- lations. read more..

  • Page - 24

    Section 1.2 The Design of C++ 9 1.2 The Design of C++ The purpose of a programming language is to help express ideas in code. In that, a programming language performs two related tasks: it provides a vehicle for the programmer to specify actions to be executed by the machine, and it provides a set of concepts for the programmer to use when thinking about what can be read more..

  • Page - 25

    10 Notes to the Reader Chapter 1 By systems programming I mean writing code that directly uses hardware resources, has serious resource constraints, or closely interacts with code that does. In particular, the implementation of software infrastructure (e.g., device drivers, communications stacks, virtual machines, operating systems, operations systems, programming environments, and foundation read more..

  • Page - 26

    Section 1.2.1 Programming Style 11 The C++ language features most directly support four programming styles: • Procedural programming • Data abstraction • Object-oriented programming • Generic programming However, the emphasis is on the support of effective combinations of those. The best (most main- tainable, most readable, smallest, fastest, etc.) solution to most nontrivial problems read more..

  • Page - 27

    12 Notes to the Reader Chapter 1 I wince when someone characterizes C++ exclusively through one of these styles (e.g., ‘‘C++ is an object-oriented language’’) or uses a term (e.g., ‘‘hybrid’’ or ‘‘mixed paradigm’’) to imply that a more restrictive language would be preferable. The former misses the fact that all the styles men- tioned have contributed something read more..

  • Page - 28

    Section 1.2.1 Programming Style 13 From the very earliest days, C++ programs and the design of C++ itself have been concerned about resource management. The ideal was (and is) for resource management to be • simple (for implementers and especially for users), • general (a resource is anything that has to be acquired from somewhere and later released), • efficient (obey the read more..

  • Page - 29

    14 Notes to the Reader Chapter 1 readable, maintainable, and analyzable. A trivial type system allows only trivial analysis, whereas a type-rich style of programming opens opportunities for nontrivial error detection and optimiza- tion. C++ compilers and development tools support such type-based analysis [Stroustrup,2012]. Maintaining most of C as a subset and preserving the direct mapping read more..

  • Page - 30

    Section 1.2.3 C Compatibility 15 area. The difference between C and C++ is primarily in the degree of emphasis on types and struc- ture. C is expressive and permissive. Through extensive use of the type system, C++ is even more expressive without loss of performance. Knowing C is not a prerequisite for learning C++. Programming in C encourages many tech- niques and tricks read more..

  • Page - 31

    16 Notes to the Reader Chapter 1 Not every piece of code can be well structured, hardware-independent, easy to read, etc. C++ possesses features that are intended for manipulating hardware facilities in a direct and efficient way without concerns for safety or ease of comprehension. It also possesses facilities for hiding such code behind elegant and safe interfaces. Naturally, the read more..

  • Page - 32

    Section 1.3 Learning C++ 17 1.3 Learning C++ No programming language is perfect. Fortunately, a programming language does not have to be perfect to be a good tool for building great systems. In fact, a general-purpose programming lan- guage cannot be perfect for all of the many tasks to which it is put. What is perfect for one task is often seriously flawed for another read more..

  • Page - 33

    18 Notes to the Reader Chapter 1 C++ programming is based on strong static type checking, and most techniques aim at achiev- ing a high level of abstraction and a direct representation of the programmer’s ideas. This can usu- ally be done without compromising run-time and space efficiency compared to lower-level tech- niques. To gain the benefits of C++, programmers coming to read more..

  • Page - 34

    Section 1.3.1 Programming in C++ 19 More specifically: [5] Prefer statically type-checked solutions (when applicable). [6] Keep information local (e.g., avoid global variables, minimize the use of pointers). [7] Don’t overabstract (i.e., don’t generalize, introduce class hierarchies, or parameterize beyond obvious needs and experience). More specific suggestions are listed in §1.3.2. 1.3.2 read more..

  • Page - 35

    20 Notes to the Reader Chapter 1 [1] Don’t think of C++ as C with a few features added. C++ can be used that way, but only suboptimally. To get really major advantages from C++ as compared to C, you need to apply different design and implementation styles. [2] Don’t write C in C++; that is often seriously suboptimal for both maintenance and perfor- mance. [3] Use read more..

  • Page - 36

    Section 1.3.4 Suggestions for Jav a Programmers 21 [2] Use the C++ abstraction mechanisms (e.g., classes and templates): don’t fall back to a C style of programming out of a false feeling of familiarity. [3] Use the C++ standard library as a teacher of new techniques and programming styles. [4] Don’t immediately invent a unique base for all of your classes (an Object read more..

  • Page - 37

    22 Notes to the Reader Chapter 1 The evolution of C++ was always in the context of its use. I spent a lot of time listening to users and seeking out the opinions of experienced programmers. In particular, my colleagues at AT&T Bell Laboratories were essential for the growth of C++ during its first decade. This section is a brief overview; it does not try to mention every read more..

  • Page - 38

    Section 1.4.1 Timeline 23 2009 C++0x was feature complete. It provided uniform initialization, move semantics, vari- adic template arguments, lambda expressions, type aliases, a memory model suitable for concurrency, and much more. The standard library added several components, including threads, locks, and most of the components from the 2003 Technical Report. 2011 ISO C++11 standard was read more..

  • Page - 39

    24 Notes to the Reader Chapter 1 able to present a set of language facilities supporting a coherent set of programming styles; see §1.2.1. In retrospect, I consider the introduction of constructors and destructors most significant. In the terminology of the time, ‘‘a constructor creates the execution environment for the member functions and the destructor reverses that.’’ Here read more..

  • Page - 40

    Section 1.4.2.1 Language Features and Library Facilities 25 The C++ language evolved hand in hand with some of the key library facilities presented in this book. For example, I designed the complex [Stroustrup,1984], vector, stack, and (I/O) stream [Stroustrup,1985] classes together with the operator overloading mechanisms. The first string and list classes were developed by Jonathan read more..

  • Page - 41

    26 Notes to the Reader Chapter 1 1.4.3.1 Language Features By the time the ANSI and ISO standards efforts started, most major language features were in place and documented in the ARM [Ellis,1989]. Consequently, most of the work involved refinement of features and their specification. The template mechanisms, in particular, benefited from much detailed work. Namespaces were introduced read more..

  • Page - 42

    Section 1.4.3.2 The Standard Library 27 time the standards work started. Thus, the committee was limited to a patchwork of components based on what had always been available (e.g., the complex library), what could be added without interfering with the major vendor’s libraries, and what was needed to ensure cooperation among different nonstandard libraries. The standard-library string read more..

  • Page - 43

    28 Notes to the Reader Chapter 1 information between tasks without explicit use of a lock,’’ which became future s and async() (§5.3.5); Lawrence Crowl and Detlef V ollmann did most of the work on that. Concurrency is an area where a complete and detailed listing of who did what and why would require a very long paper. Here, I can’t even try. 1.4.4.1 Language Features The read more..

  • Page - 44

    Section 1.4.4.1 Language Features 29 Many more people than can be listed here deserve to be mentioned. The technical reports to the committee [WG21] and my C++11 FAQ [Stroustrup,2010a] give many of the names. The minutes of the committee’s working groups mention more still. The reason my name appears so often is (I hope) not vanity, but simply that I chose to work on read more..

  • Page - 45

    30 Notes to the Reader Chapter 1 • The tuple library: §5.4.3, §28.5, §34.2.4.2; Jaakko Jarvi and Gary Powell. They credit a long list of contributors, including Doug Gregor, David Abrahams, and Jeremy Siek. • The general bind() : §33.5.1; Peter Dimov. His acknowledgments list a veritable who’s who of Boost (including Doug Gregor, John Maddock, Dave Abrahams, and Jaakko Jarvi). read more..

  • Page - 46

    Section 1.4.5 What is C++ used for? 31 Games is another area where a multiplicity of languages and tools need to coexist with a lan- guage providing uncompromising efficiency (often on ‘‘unusual’’ hardware). Thus, games has been another major applications area for C++. What used to be called systems programming is widely found in embedded systems, so it is not surprising read more..

  • Page - 47

    32 Notes to the Reader Chapter 1 [1] Represent ideas (concepts) directly in code, for example, as a function, a class, or an enu- meration; §1.2. [2] Aim for your code to be both elegant and efficient; §1.2. [3] Don’t overabstract; §1.2. [4] Focus design on the provision of elegant and efficient abstractions, possibly presented as libraries; §1.2. [5] Represent relationships read more..

  • Page - 48

    Section 1.6 References 33 [C,1990] X3 Secretariat: Standard – The C Language. X3J11/90-013. ISO Standard ISO/IEC 9899-1990. Computer and Business Equipment Manufacturers Association. Washington, DC. [C,1999] ISO/IEC 9899. Standard – The C Language. X3J11/90-013-1999. [C,2011] ISO/IEC 9899. Standard – The C Language. X3J11/90-013-2011. [C++,1998] ISO/IEC JTC1/SC22/WG21: International Standard – The read more..

  • Page - 49

    34 Notes to the Reader Chapter 1 [Gamma,1995] Erich Gamma et al.: Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. Reading, Massachusetts. 1994. ISBN 0-201-63361-2. [Gregor,2006] Douglas Gregor et al.: Concepts: Linguistic Support for Generic Program- ming in C++. OOPSLA’06. [Hennessy,2011] John L. Hennessy and David A. Patterson: Computer Architecture, Fifth Edi- read more..

  • Page - 50

    Section 1.6 References 35 Web address. [Rozier,1988] M. Rozier et al.: CHORUS Distributed Operating Systems. Computing Sys- tems. Vol. 1, No. 4. Fall 1988. [Siek,2000] Jeremy G. Siek and Andrew Lumsdaine: Concept checking: Binding para- metric polymorphism in C++. Proc. First Workshop on C++ Template Pro- gramming. Erfurt, Germany. 2000. [Solodkyy,2012] Y. Solodkyy, G. Dos Reis, and B. read more..

  • Page - 51

    36 Notes to the Reader Chapter 1 [Stroustrup,2008] B. Stroustrup: Programming – Principles and Practice Using C++. Addi- son-Wesley. 2009. ISBN 0-321-54372-6. [Stroustrup,2010a] B. Stroustrup: The C++11 FAQ. www.stroustrup.com/C++11FAQ.html. [Stroustrup,2010b] B. Stroustrup: The C++0x ‘‘Remove Concepts’’ Decision. Dr. Dobb’s Jour- nal. July 2009. [Stroustrup,2012a] B. Stroustrup and A. Sutton: A read more..

  • Page - 52

    2 A Tour of C++: The Basics The first thing we do, let’s kill all the language lawyers. – Henry VI, Part II • Introduction • The Basics Hello, World!; Types, Variables, and Arithmetic; Constants; Tests and Loops; Pointers, Arrays, and Loops • User-Defined Types Structures; Classes; Enumerations • Modularity Separate Compilation; Namespaces; Error Handling • Postscript • Advice 2.1 read more..

  • Page - 53

    38 A Tour of C++: The Basics Chapter 2 This tour of C++ saves us from a strictly bottom-up presentation of language and library facili- ties by enabling the use of a rich set of facilities even in early chapters. For example, loops are not discussed in detail until Chapter 10, but they will be used in obvious ways long before that. Simi- larly, the detailed description read more..

  • Page - 54

    Section 2.2.1 Hello, World! 39 2.2.1 Hello, World! The minimal C++ program is int main() { } // the minimal C++ program This defines a function called main , which takes no arguments and does nothing (§15.4). Curly braces, {} , express grouping in C++. Here, they indicate the start and end of the function body. The double slash, // , begins a comment that extends to the read more..

  • Page - 55

    40 A Tour of C++: The Basics Chapter 2 void print_square(double x) { cout << "the square of " << x << " is " << square(x) << "\n"; } int main() { print_square(1.234); // print: the square of 1.234 is 1.52276 } A ‘‘return type’’ void indicates that a function does not return a value. 2.2.2 Types, Variables, and Arithmetic Every name and every read more..

  • Page - 56

    Section 2.2.2 Types, Variables, and Arithmetic 41 x+y // plus +x // unar y plus x y // minus x // unar y minus x ∗y// multiply x/y // divide x%y // remainder (modulus) for integers So can the comparison operators: x==y // equal x!=y // not equal x<y // less than x>y // greater than x<=y // less than or equal x>=y // greater than or equal In assignments and in read more..

  • Page - 57

    42 A Tour of C++: The Basics Chapter 2 When defining a variable, you don’t actually need to state its type explicitly when it can be deduced from the initializer: auto b = true; // a bool auto ch = 'x'; // a char auto i = 123; // an int auto d = 1.2; // a double auto z = sqrt(y); // z has the type of whatever sqr t(y) retur ns With auto , we use the read more..

  • Page - 58

    Section 2.2.3 Constants 43 double sum(const vector<double>&); // sum will not modify its argument (§2.2.5) vector<double> v {1.2, 3.4, 4.5}; // v is not a constant const double s1 = sum(v); // OK: evaluated at run time constexpr double s2 = sum(v); // error : sum(v) not constant expression For a function to be usable in a constant expression, that is, in an read more..

  • Page - 59

    44 A Tour of C++: The Basics Chapter 2 switch (answer) { case 'y': return true; case 'n': return false; default: cout << "I'll take that for a no.\n"; return false; } } A switch -statement tests a value against a set of constants. The case constants must be distinct, and if the value tested does not match any of them, the default is chosen. If no default is read more..

  • Page - 60

    Section 2.2.5 Pointers, Arrays, and Loops 45 bound, so v has six elements, v[0] to v[5] . The size of an array must be a constant expression (§2.2.3). A pointer variable can hold the address of an object of the appropriate type: char ∗ p = &v[3]; // p points to v’s four th element char x = ∗p; // *p is the object that p points to In an expression, prefix read more..

  • Page - 61

    46 A Tour of C++: The Basics Chapter 2 void increment() { int v[] = {0,1,2,3,4,5,6,7,8,9}; for (auto& x : v) ++x; // ... } In a declaration, the unary suffix & means ‘‘reference to.’ ’ A reference is similar to a pointer, except that you don’t need to use a prefix ∗ to access the value referred to by the reference. Also, a reference cannot be made to read more..

  • Page - 62

    Section 2.3 User-Defined Types 47 2.3 User-Defined Types We call the types that can be built from the fundamental types (§2.2.2), the const modifier (§2.2.3), and the declarator operators (§2.2.5) built-in types. C++’s set of built-in types and operations is rich, but deliberately low-level. They directly and efficiently reflect the capabilities of conventional computer hardware. read more..

  • Page - 63

    48 A Tour of C++: The Basics Chapter 2 A simple use of Vector looks like this: double read_and_sum(int s) // read s integers from cin and return their sum; s is assumed to be positive { Vector v; vector_init(v,s); // allocate s elements for v for (int i=0; i!=s; ++i) cin>>v.elem[i]; // read into elements double sum = 0; for (int i=0; i!=s; ++i) sum+=v.elem[i]; // take read more..

  • Page - 64

    Section 2.3.2 Classes 49 class Vector { public: Vector(int s) :elem{new double[s]}, sz{s} { } // constr uct a Vector double& operator[](int i) { return elem[i]; } // element access: subscripting int size() { return sz; } private: double ∗ elem; // pointer to the elements int sz; // the number of elements }; Given that, we can define a variable of our new type Vector : Vector read more..

  • Page - 65

    50 A Tour of C++: The Basics Chapter 2 Vector(int) defines how objects of type Vector are constructed. In particular, it states that it needs an integer to do that. That integer is used as the number of elements. The constructor initializes the Vector members using a member initializer list: :elem{new double[s]}, sz{s} That is, we first initialize elem with a pointer to s read more..

  • Page - 66

    Section 2.3.3 Enumerations 51 Traf c_light& operator++(Traf c_light& t) // prefix increment: ++ { switch (t) { case Traf c_light::green: return t=Traf c_light::yellow; case Traf c_light::yellow: return t=Traf c_light::red; case Traf c_light::red: return t=Traf c_light::green; } } Traf c_light next = ++light; // next becomes Traffic_light::green C++ also offers a less strongly typed read more..

  • Page - 67

    52 A Tour of C++: The Basics Chapter 2 double& Vector::operator[](int i) // definition of subscripting { return elem[i]; } int Vector::siz e() // definition of size() { return sz; } We must define Vector ’s functions, but not sqrt() because it is part of the standard library. Howev er, that makes no real difference: a library is simply some ‘‘other code we happen to use’ read more..

  • Page - 68

    Section 2.4.1 Separate Compilation 53 double sqrt_sum(Vector& v) { double sum = 0; for (int i=0; i!=v.siz e(); ++i) sum+=sqrt(v[i]); // sum of square roots return sum; } To help the compiler ensure consistency, the .cpp file providing the implementation of Vector will also include the .h file providing its interface: // Vector.cpp: #include "Vector.h" // get the interface read more..

  • Page - 69

    54 A Tour of C++: The Basics Chapter 2 2.4.2 Namespaces In addition to functions (§2.2.1, Chapter 12), classes (Chapter 16), and enumerations (§2.3.3, §8.4), C++ offers namespaces (Chapter 14) as a mechanism for expressing that some declarations belong together and that their names shouldn’t clash with other names. For example, I might want to experiment with my own complex number type read more..

  • Page - 70

    Section 2.4.3 Error Handling 55 and increase the compiler’s chances of catching such errors. The majority of C++ constructs are dedicated to the design and implementation of elegant and efficient abstractions (e.g., user-defined types and algorithms using them). One effect of this modularity and abstraction (in particular, the use of libraries) is that the point where a run-time read more..

  • Page - 71

    56 A Tour of C++: The Basics Chapter 2 2.4.3.2 Invariants The use of exceptions to signal out-of-range access is an example of a function checking its argu- ment and refusing to act because a basic assumption, a precondition, didn’t hold. Had we formally specified Vector ’s subscript operator, we would have said something like ‘‘the inde x must be in the [0:size()) read more..

  • Page - 72

    Section 2.4.3.2 Invariants 57 The notion of invariants is central to the design of classes, and preconditions serve a similar role in the design of functions. Invariants • helps us to understand precisely what we want • forces us to be specific; that gives us a better chance of getting our code correct (after debugging and testing). The notion of invariants underlies C++’s read more..

  • Page - 73

    58 A Tour of C++: The Basics Chapter 2 2.6 Advice [1] Don’t panic! All will become clear in time; §2.1. [2] You don’t hav e to know every detail of C++ to write good programs; §1.3.1. [3] Focus on programming techniques, not on language features; §2.1. read more..

  • Page - 74

    3 A Tour of C++: Abstraction Mechanisms Don’t Panic! – Douglas Adams • Introduction • Classes Concrete Types; Abstract Types; Virtual Functions; Class Hierarchies • Copy and Move Copying Containers; Moving Containers; Resource Management; Suppressing Operations • Templates Parameterized Types; Function Templates; Function Objects; Variadic Templates; Aliases • Advice 3.1 Introduction This chapter read more..

  • Page - 75

    60 A Tour of C++: Abstraction Mechanisms Chapter 3 As in Chapter 2, this tour presents C++ as an integrated whole, rather than as a layer cake. Consequently, it does not identify language features as present in C, part of C++98, or new in C++11. Such historical information can be found in §1.4 and Chapter 44. 3.2 Classes The central language feature of C++ is the class. A read more..

  • Page - 76

    Section 3.2.1 Concrete Types 61 types. For types that don’t change often, and where local variables provide much-needed clarity and efficiency, this is acceptable and often ideal. To increase flexibility, a concrete type can keep major parts of its representation on the free store (dynamic memory, heap) and access them through the part stored in the class object itself. read more..

  • Page - 77

    62 A Tour of C++: Abstraction Mechanisms Chapter 3 complex operator+(complex a, complex b) { return a+=b; } complex operator (complex a, complex b) { return a =b; } complex operator (complex a) { return { a.real(), a.imag()}; } // unar y minus complex operator ∗(complex a, complex b) { return a ∗=b; } complex operator/(complex a, complex b) { return a/=b; } Here, I use read more..

  • Page - 78

    Section 3.2.1.2 A Container 63 guaranteed that one is available to make unused memory available for new objects. In some envi- ronments you can’t use a collector, and sometimes you prefer more precise control of destruction (§13.6.4) for logical or performance reasons. We need a mechanism to ensure that the memory allocated by the constructor is deallocated; that mechanism is a read more..

  • Page - 79

    64 A Tour of C++: Abstraction Mechanisms Chapter 3 6 Vector : elem : sz : 0 0 0 0 0 0 0: 1: 2: 3: 4: 5: The constructor allocates the elements and initializes the Vector members appropriately. The de- structor deallocates the elements. This handle-to-data model is very commonly used to manage data that can vary in size during the lifetime of an object. The technique of acquiring read more..

  • Page - 80

    Section 3.2.1.3 Initializing Containers 65 The std::initializer_list used to define the initializer-list constructor is a standard-library type known to the compiler: when we use a {} -list, such as {1,2,3,4} , the compiler will create an object of type initializer_list to give to the program. So, we can write: Vector v1 = {1,2,3,4,5}; // v1 has 5 elements Vector v2 = {1.23, 3.45, read more..

  • Page - 81

    66 A Tour of C++: Abstraction Mechanisms Chapter 3 Note how use() uses the Container interface in complete ignorance of implementation details. It uses size() and [] without any idea of exactly which type provides their implementation. A class that provides the interface to a variety of other classes is often called a polymorphic type (§20.3.2). As is common for abstract classes, read more..

  • Page - 82

    Section 3.2.2 Abstract Types 67 double& operator[](int i); int size() const { return ld.size(); } }; double& List_container::operator[](int i) { for (auto& x : ld) { if (i==0) return x; i; } throw out_of_rang e("List container"); } Here, the representation is a standard-library list<double> . Usually, I would not implement a con- tainer with a subscript operation using a read more..

  • Page - 83

    68 A Tour of C++: Abstraction Mechanisms Chapter 3 called the virtual function table or simply the vtbl . Each class with virtual functions has its own vtbl identifying its virtual functions. This can be represented graphically like this: v Vector_container::operator[]() Vector_container::siz e() Vector_container::˜Vector_container() vtbl : Vector_container : ld List_container::operator[]() read more..

  • Page - 84

    Section 3.2.4 Class Hierarchies 69 class Shape { public: virtual Point center() const =0; // pure virtual virtual void move(Point to) =0; virtual void draw() const = 0; // draw on current "Canvas" virtual void rotate(int angle) = 0; virtual ˜Shape() {} // destructor // ... }; Naturally, this interface is an abstract class: as far as representation is concerned, nothing (except read more..

  • Page - 85

    70 A Tour of C++: Abstraction Mechanisms Chapter 3 void move(Point to); void draw() const; void rotate(int); void add_eye(Shape ∗ s) { eyes.push_back(s); } void set_mouth(Shape ∗ s); virtual void wink(int i); // wink eye number i // ... private: vector<Shape ∗> eyes; // usually two eyes Shape ∗ mouth; }; The push_back() member function adds its argument to the vector (here, eyes read more..

  • Page - 86

    Section 3.2.4 Class Hierarchies 71 them through pointers or references. For example, consider a function that reads data describing shapes from an input stream and constructs the appropriate Shape objects: enum class Kind { circle, triangle , smiley }; Shape ∗ read_shape(istream& is) // read shape descriptions from input stream is { // ... read shape header from is and find its read more..

  • Page - 87

    72 A Tour of C++: Abstraction Mechanisms Chapter 3 One solution to both problems is to return a standard-library unique_ptr (§5.2.1) rather than a ‘‘naked pointer’’ and store unique_ptr s in the container: unique_ptr<Shape> read_shape(istream& is) // read shape descriptions from input stream is { // read shape header from is and find its Kind k switch (k) { case Kind::circle: read more..

  • Page - 88

    Section 3.3.1 Copying Containers 73 3.3.1 Copying Containers When a class is a resource handle, that is, it is responsible for an object accessed through a pointer, the default memberwise copy is typically a disaster. Memberwise copy would violate the resource handle’s inv ariant (§2.4.3.2). For example, the default copy would leave a copy of a Vector refer- ring to the read more..

  • Page - 89

    74 A Tour of C++: Abstraction Mechanisms Chapter 3 Vector::Vector(const Vector& a) // copy constr uctor :elem{new double[sz]}, // allocate space for elements sz{a.sz} { for (int i=0; i!=sz; ++i) // copy elements elem[i] = a.elem[i]; } The result of the v2=v1 example can now be presented as: 4 v1 : 4 v2 : 3 2 Of course, we need a copy assignment in addition to the copy read more..

  • Page - 90

    Section 3.3.2 Moving Containers 75 Returning from a + involves copying the result out of the local variable res and into some place where the caller can access it. We might use this + like this: void f(const Vector& x, const Vector& y, const Vector& z) { Vector r; // ... r = x+y+z; // ... } That would be copying a Vector at least twice (one for each use of the + read more..

  • Page - 91

    76 A Tour of C++: Abstraction Mechanisms Chapter 3 After a move, a moved-from object should be in a state that allows a destructor to be run. Typi- cally, we should also allow assignment to a moved-from object (§17.5, §17.6.2). Where the programmer knows that a value will not be used again, but the compiler can’t be expected to be smart enough to figure that out, the read more..

  • Page - 92

    Section 3.3.3 Resource Management 77 Vector vec(n); for (int i=0; i<vec.size(); ++i) vec[i] = 777; return vec; // move res out of init() } auto v = init(); // star t hear tbeat and initialize v This makes resource handles, such as Vector and thread , an alternative to using pointers in many cases. In fact, the standard-library ‘‘smart pointers,’’ such as unique_ptr , are read more..

  • Page - 93

    78 A Tour of C++: Abstraction Mechanisms Chapter 3 3.4 Templates Someone who wants a vector is unlikely always to want a vector of double s. A vector is a general concept, independent of the notion of a floating-point number. Consequently, the element type of a vector ought to be represented independently. A template is a class or a function that we parame- terize with a read more..

  • Page - 94

    Section 3.4.1 Parameterized Types 79 Given these definitions, we can define Vector s like this: Vector<char> vc(200); // vector of 200 characters Vector<string> vs(17); // vector of 17 strings Vector<list<int>> vli(45); // vector of 45 lists of integers The >> in Vector<list<int>> terminates the nested template arguments; it is not a misplaced input operator. It read more..

  • Page - 95

    80 A Tour of C++: Abstraction Mechanisms Chapter 3 template<typename Container, typename Value> Value sum(const Container& c, V alue v) { for (auto x : c) v+=x; return v; } The Value template argument and the function argument v are there to allow the caller to specify the type and initial value of the accumulator (the variable in which to accumulate the sum): void read more..

  • Page - 96

    Section 3.4.3 Function Objects 81 Such function objects are widely used as arguments to algorithms. For example, we can count the occurrences of values for which a predicate returns true : template<typename C, typename P> int count(const C& c, P pred) { int cnt = 0; for (const auto& x : c) if (pred(x)) ++cnt; return cnt; } A predicate is something that we can invoke to read more..

  • Page - 97

    82 A Tour of C++: Abstraction Mechanisms Chapter 3 so: [&x] . Had we wanted to give the generated object a copy of x , we could have said so: [=x] . Cap- ture nothing is [] , capture all local names used by reference is [&] , and capture all local names used by value is [=] . Using lambdas can be convenient and terse, but also obscure. For nontrivial read more..

  • Page - 98

    Section 3.4.4 Variadic Templates 83 you can separate the first argument from the rest. Here, we do something to the first argument (the head ) and then recursively call f() with the rest of the arguments (the tail ). The ellipsis, ... , is used to indicate ‘‘the rest’’ of a list. Eventually, of course, tail will become empty and we need a separate function to deal read more..

  • Page - 99

    84 A Tour of C++: Abstraction Mechanisms Chapter 3 template<typename T> class Vector { public: using value_type = T; // ... }; In fact, every standard-library container provides value_type as the name of its value type (§31.3.1). This allows us to write code that will work for every container that follows this convention. For example: template<typename C> using Element_type = read more..

  • Page - 100

    Section 3.5 Advice 85 [8] When designing a class hierarchy, distinguish between implementation inheritance and inter- face inheritance; §3.2.4. [9] Control construction, copy, move, and destruction of objects; §3.3. [10] Return containers by value (relying on move for efficiency); §3.3.2. [11] Provide strong resource safety; that is, never leak anything that you think of as a read more..

  • Page - 101

    This page intentionally left blank read more..

  • Page - 102

    4 A Tour of C++: Containers and Algorithms Why waste time learning when ignorance is instantaneous? – Hobbes • Libraries Standard-Library Overview; The Standard-Library Headers and Namespace • Strings • Stream I/O Output; Input; I/O of User-Defined Types • Containers vector ; list ; map ; unordered_map ; Container Overview • Algorithms Use of Iterators; Iterator Types; Stream Iterators; read more..

  • Page - 103

    88 A Tour of C++: Containers and Algorithms Chapter 4 I very briefly present useful standard-library types, such as string , ostream , vector , map (this chapter), unique_ptr , thread , regex , and complex (Chapter 5), as well as the most common ways of using them. Doing this allows me to give better examples in the following chapters. As in Chapter 2 and Chapter 3, you read more..

  • Page - 104

    Section 4.1.1 Standard-Library Overview 89 The main criteria for including a class in the library were that: • it could be helpful to almost every C++ programmer (both novices and experts), • it could be provided in a general form that did not add significant overhead compared to a simpler version of the same facility, and • that simple uses should be easy to learn read more..

  • Page - 105

    90 A Tour of C++: Containers and Algorithms Chapter 4 Selected Standard Library Headers (continued) <map> map , multimap §31.4.3 §iso.23.4.4 <memory> unique_ptr , shared_ptr , allocator §5.2.1 §iso.20.6 <random> default_random_engine , normal_distribution §40.7 §iso.26.5 <regex> rege x , smatch Chapter 37 §iso.28.8 <string> string , basic_string Chapter 36 §iso.21.3 <set> set , multiset read more..

  • Page - 106

    Section 4.2 Strings 91 string name = "Niels Str oustrup"; void m3() { string s = name.substr(6,10); // s = "Stroustr up" name.replace(0,5,"nicholas"); // name becomes "nicholas Stroustrup" name[0] = toupper(name[0]); // name becomes "Nicholas Stroustrup" } The substr() operation returns a string that is a copy of the substring indicated by its arguments. The read more..

  • Page - 107

    92 A Tour of C++: Containers and Algorithms Chapter 4 type ostream ; cout is the standard output stream and cerr is the standard stream for reporting errors. By default, values written to cout are converted to a sequence of characters. For example, to output the decimal number 10 , we can write: void f() { cout << 10; } This places the character 1 followed by the read more..

  • Page - 108

    Section 4.3.2 Input 93 4.3.2 Input The standard library offers istream s for input. Like ostream s, istream s deal with character string representations of built-in types and can easily be extended to cope with user-defined types. The operator >> (‘‘get from’’) is used as an input operator; cin is the standard input stream. The type of the right-hand operand of >> read more..

  • Page - 109

    94 A Tour of C++: Containers and Algorithms Chapter 4 The newline that terminated the line is discarded, so cin is ready for the next input line. The standard strings have the nice property of expanding to hold what you put in them; you don’t hav e to precalculate a maximum size. So, if you enter a couple of megabytes of semicolons, the program will echo pages of read more..

  • Page - 110

    Section 4.3.3 I/O of User-Defined Types 95 succeeded. For example, when used as a condition, is>>c means ‘‘Did we succeed at reading from is into c ?’’ The is>>c skips whitespace by default, but is.g et(c) does not, so that this Entr y -input operator ignores (skips) whitespace outside the name string, but not within it. For example: { "John Marwood Cleese" , 123456 } read more..

  • Page - 111

    96 A Tour of C++: Containers and Algorithms Chapter 4 We can initialize a vector with a set of values of its element type: vector<Entry> phone_book = { {"David Hume",123456}, {"Karl Popper",234567}, {"Bertrand Ar thur William Russell",345678} }; Elements can be accessed through subscripting: void print_book(const vector<Entry>& book) { for (int i = 0; read more..

  • Page - 112

    Section 4.4.1 vector 97 Copying and moving of vector s are implemented by constructors and assignment operators as described in §3.3. Assigning a vector involves copying its elements. Thus, after the initialization of book2 , book2 and phone_book hold separate copies of every Entry in the phone book. When a vector holds many elements, such innocent-looking assignments and initializations read more..

  • Page - 113

    98 A Tour of C++: Containers and Algorithms Chapter 4 For Vec , an out-of-range access will throw an exception that the user can catch. For example: void checked(Vec<Entr y>& book) { try { book[book.size()] = {"Joe",999999}; // will throw an exception // ... } catch (out_of_rang e) { cout << "range error\n"; } } The exception will be thrown, and then caught read more..

  • Page - 114

    Section 4.4.2 list 99 {"Karl Popper",234567}, {"Bertrand Ar thur William Russell",345678} }; When we use a linked list, we tend not to access elements using subscripting the way we com- monly do for vectors. Instead, we might search the list looking for an element with a given value. To do this, we take advantage of the fact that a list is a sequence as read more..

  • Page - 115

    100 A Tour of C++: Containers and Algorithms Chapter 4 4.4.3 map Writing code to look up a name in a list of (name,number) pairs is quite tedious. In addition, a lin- ear search is inefficient for all but the shortest lists. The standard library offers a search tree (a red- black tree) called map : 4 map : links key : value : links links links In other contexts, a map is read more..

  • Page - 116

    Section 4.4.4 unordered_map 101 containers are referred to as ‘‘unordered’’ because they don’t require an ordering function: rep unordered_map : hash table: For example, we can use an unordered_map from <unordered_map> for our phone book: unordered_map<string,int> phone_book { {"David Hume",123456}, {"Karl Popper",234567}, {"Bertrand Ar thur William Russell",345678} }; As read more..

  • Page - 117

    102 A Tour of C++: Containers and Algorithms Chapter 4 The standard containers are described in §31.4. The containers are defined in namespace std and presented in headers <vector> , <list> , <map> , etc. (§4.1.2, §30.2). In addition, the standard library provides container adaptors queue<T> (§31.5.2), stack<T> (§31.5.1), deque<T> (§31.4), and read more..

  • Page - 118

    Section 4.5 Algorithms 103 elements: begin() end() iterators: In the example, sor t() sorts the sequence defined by the pair of iterators vec.begin() and vec.end() – which just happens to be all the elements of a vector . For writing (output), you need only to specify the first element to be written. If more than one element is written, the elements following that ini- tial read more..

  • Page - 119

    104 A Tour of C++: Containers and Algorithms Chapter 4 bool has_c(const string& s, c har c) // does s contain the character c? { return nd(s.begin(),s.end(),c)!=s.end(); } A more interesting exercise would be to find the location of all occurrences of a character in a string. We can return the set of occurrences as a vector of string iterators. Returning a vector is efficient read more..

  • Page - 120

    Section 4.5.1 Use of Iterators 105 The typename is needed to inform the compiler that C ’s iterator is supposed to be a type and not a value of some type, say, the integer 7 . We can hide this implementation detail by introducing a type alias (§3.4.5) for Iterator : template<typename T> using Iterator<T> = typename T::iterator; template<typename C, typename V> read more..

  • Page - 121

    106 A Tour of C++: Containers and Algorithms Chapter 4 its job for a particular container type. These iterator types can be as different as the containers and the specialized needs they serve. For example, a vector ’s iterator could be an ordinary pointer, because a pointer is quite a reasonable way of referring to an element of a vector : P i e t H e i n vector: p read more..

  • Page - 122

    Section 4.5.3 Stream Iterators 107 ostream_iterator<string> oo {cout}; // write str ings to cout The effect of assigning to ∗oo is to write the assigned value to cout. For example: int main() { ∗oo = "Hello, "; // meaning cout<<"Hello, " ++oo; ∗oo = "world!\n"; // meaning cout<<"wor ld!\n" } This is yet another way of writing the canonical read more..

  • Page - 123

    108 A Tour of C++: Containers and Algorithms Chapter 4 store duplicates at all. This can be done by keeping the string sina set , which does not keep dupli- cates and keeps its elements in order (§31.4.3). That way, we could replace the two lines using a vector with one using a set and replace unique_copy() with the simpler copy() : set<string> b {ii,eos}; // collect read more..

  • Page - 124

    Section 4.5.4 Predicates 109 4.5.5 Algorithm Overview A general definition of an algorithm is ‘‘a finite set of rules which gives a sequence of operations for solving a specific set of problems [and] has five important features: Finiteness ... Definiteness ... Input ... Output ... Effectiveness’’ [Knuth,1968,§1.1]. In the context of the C++ standard library, an algorithm is a read more..

  • Page - 125

    110 A Tour of C++: Containers and Algorithms Chapter 4 template<class C, class Pred> void sort(C& c, Pred p) { sort(c.begin(),c.end(),p); } // ... } I put the container versions of sort() (and other algorithms) into their own namespace Estd (‘‘extended std ’’) to avoid interfering with other programmers’ uses of namespace std . 4.6 Advice [1] Don’t reinvent the wheel; use read more..

  • Page - 126

    5 A Tour of C++: Concurrency and Utilities When you wish to instruct, be brief. – Cicero • Introduction • Resource Management unique_ptr and shared_ptr • Concurrency Tasks and thread s; Passing Arguments; Returning Results; Sharing Data; Communicating Tasks • Small Utility Components Time; Type Functions; pair and tuple • Regular Expressions • Math Mathematical Functions and Algorithms; read more..

  • Page - 127

    112 A Tour of C++: Concurrency and Utilities Chapter 5 5.2 Resource Management One of the key tasks of any nontrivial program is to manage resources. A resource is something that must be acquired and later (explicitly or implicitly) released. Examples are memory, locks, sockets, thread handles, and file handles. For a long-running program, failing to release a resource in a read more..

  • Page - 128

    Section 5.2.1 unique_ptr and shared_ptr 113 if (i<99) thr ow Z{}; // may throw an exception if (j<77) return; // may retur n "ear ly" p >do_something(); // may throw an exception sp >do_something(); // may throw an exception // ... delete p; // destroy *p } Here, we ‘‘forgot’’ to delete p if i<99 or if j<77 . On the other hand, unique_ptr ensures that its read more..

  • Page - 129

    114 A Tour of C++: Concurrency and Utilities Chapter 5 Now, the file opened by fp ’s constructor will be closed by the last function to (explicitly or implic- itly) destroy a copy of fp . Note that f() or g() may spawn a task holding a copy of fp or in some other way store a copy that outlives user() . Thus, shared_ptr provides a form of garbage collection that read more..

  • Page - 130

    Section 5.3.1 Tasks and thread s 115 5.3.1 Tasks and thread s We call a computation that can potentially be executed concurrently with other computations a task. A thread is the system-level representation of a task in a program. A task to be executed concur- rently with other tasks is launched by constructing a std::thread (found in <thread> ) with the task as its read more..

  • Page - 131

    116 A Tour of C++: Concurrency and Utilities Chapter 5 5.3.2 Passing Arguments Typically, a task needs data to work upon. We can easily pass data (or pointers or references to the data) as arguments. Consider: void f(vector<double>& v); // function do something with v struct F { // function object: do something with v vector<double>& v; F(vector<double>& vv) :v{vv} read more..

  • Page - 132

    Section 5.3.3 Returning Results 117 private: const vector<double>& v; // source of input double ∗ res; // target for output }; int main() { vector<double> some_vec; vector<double> vec2; // ... double res1; double res2; thread t1 {f,some_vec,&res1}; // f(some_vec,&res1) ex ecutes in a separate thread thread t2 {F{vec2,&res2}}; // F{vec2,&res2}() ex ecutes in a separate thread read more..

  • Page - 133

    118 A Tour of C++: Concurrency and Utilities Chapter 5 The correspondence between the shared data and a mutex is conventional: the programmer simply has to know which mutex is supposed to correspond to which data. Obviously, this is error-prone, and equally obviously we try to make the correspondence clear through various language means. For example: class Record { public: mutex rm; read more..

  • Page - 134

    Section 5.3.4.1 Waiting for Events 119 using namespace std::chrono; // see §35.2 auto t0 = high_resolution_clock::now(); this_thread::sleep_for(milliseconds{20}); auto t1 = high_resolution_clock::now(); cout << duration_cast<nanoseconds>(t1 t0).count() << " nanoseconds passed\n"; Note that I didn’t even hav e to launch a thread ; by default, this_thread refers to the one and only read more..

  • Page - 135

    120 A Tour of C++: Concurrency and Utilities Chapter 5 void producer() { while(true) { Message m; // ... fill the message ... unique_lock<mutex> lck {mmutex}; // protect operations mqueue.push(m); mcond.notify_one(); // notify }// release lock (at end of scope) } Using condition_variable s supports many forms of elegant and efficient sharing, but can be rather tricky (§42.3.4). 5.3.5 read more..

  • Page - 136

    Section 5.3.5.1 future and promise 121 The main purpose of a promise is to provide simple ‘‘put’’ operations (called set_value() and set_exception() ) to match future ’s get() . The names ‘‘future’’ and ‘‘promise’’ are historical; please don’t blame me. They are yet another fertile source of puns. If you have a promise and need to send a result of type X to read more..

  • Page - 137

    122 A Tour of C++: Concurrency and Utilities Chapter 5 double accum(double ∗ beg, double ∗ end, double init) // compute the sum of [beg:end) starting with the initial value init { return accumulate(beg,end,init); } double comp2(vector<double>& v) { using Task_type = double(double ∗,double∗,double); // type of task packaged_task<Task_type> pt0 {accum}; // package the task (i.e., read more..

  • Page - 138

    Section 5.3.5.3 async() 123 auto f0 = async(accum,v0,v0+sz/4,0.0); // first quarter auto f1 = async(accum,v0+sz/4,v0+sz/2,0.0); // second quarter auto f2 = async(accum,v0+sz/2,v0+sz ∗3/4,0.0); // third quarter auto f3 = async(accum,v0+sz ∗3/4,v0+sz,0.0); // four th quar ter return f0.get()+f1.g et()+f2.get()+f3.get(); // collect and combine the results } Basically, async() separates the ‘‘call read more..

  • Page - 139

    124 A Tour of C++: Concurrency and Utilities Chapter 5 The standard-library facilities for dealing with time are found in the subnamespace std::chrono in <chrono> (§35.2). Don’t make statements about ‘‘efficiency’’ of code without first doing time measurements. Guesses about performance are most unreliable. 5.4.2 Type Functions A type function is a function that is evaluated read more..

  • Page - 140

    Section 5.4.2.1 iterator_traits 125 template<typename Ran> // for random-access iterators void sort_helper(Ran beg, Ran end, random_access_iterator_tag) // we can subscript into [beg:end) { sort(beg,end); // just sort it } The version for forward iterators is almost as simple; just copy the list into a vector , sort, and copy back again: template<typename For> // for forward iterators read more..

  • Page - 141

    126 A Tour of C++: Concurrency and Utilities Chapter 5 5.4.2.2 Type Predicates A standard-library type predicate is a simple type function that answers a fundamental question about types. For example: bool b1 = Is_arithmetic<int>(); // yes, int is an arithmetic type bool b2 = Is_arithmetic<string>(); // no, std::str ing is not an arithmetic type These predicates are found read more..

  • Page - 142

    Section 5.4.3 pair and tuple 127 for (auto p = er. rst; p!=er.second; ++p) // print all equal records cout << ∗p; // assume that << is defined for Record } The first member of a pair is called rst and the second member is called second . This naming is not particularly creative and may look a bit odd at first, but such consistent naming is a boon when we read more..

  • Page - 143

    128 A Tour of C++: Concurrency and Utilities Chapter 5 People who have used regular expressions in just about any language will find \w{2}\s ∗\d{5}( \d{4})? familiar. It specifies a pattern starting with two letters \w{2} optionally followed by some space \s ∗ followed by five digits \d{5} and optionally followed by a dash and four digits \d{4} . If you are not familiar read more..

  • Page - 144

    Section 5.6.2 Complex Numbers 129 5.6.2 Complex Numbers The standard library supports a family of complex number types along the lines of the complex class described in §2.3. To support complex numbers where the scalars are single-precision float- ing-point numbers ( oat s), double-precision floating-point numbers (doubles), etc., the standard library complex is a template: read more..

  • Page - 145

    130 A Tour of C++: Concurrency and Utilities Chapter 5 Thanks to its uncompromising attention to generality and performance one expert has deemed the standard-library random number component ‘‘what ev ery random number library wants to be when it grows up.’’ Howev er, it can hardly be deemed ‘‘novice friendly.’’ The using statements makes what is being done a bit read more..

  • Page - 146

    Section 5.6.3 Random Numbers 131 There is no standard graphics library for C++, so I use ‘‘ASCII graphics.’’ Obviously, there are lots of open source and commercial graphics and GUI libraries for C++, but in this book I’ll restrict myself to ISO standard facilities. For more information about random numbers, see §40.7. 5.6.4 Vector Arithmetic The vector described in §4.4.1 w read more..

  • Page - 147

    132 A Tour of C++: Concurrency and Utilities Chapter 5 5.7 Advice [1] Use resource handles to manage resources (RAII); §5.2. [2] Use unique_ptr to refer to objects of polymorphic type; §5.2.1. [3] Use shared_ptr to refer to shared objects; §5.2.1. [4] Use type-safe mechanisms for concurrency; §5.3. [5] Minimize the use of shared data; §5.3.4. [6] Don’t choose shared data for read more..

  • Page - 148

    Part II Basic Facilities This part describes C++’s built-in types and the basic facilities for constructing pro- grams out of them. The C subset of C++ is presented together with C++’s additional support for traditional styles of programming. It also discusses the basic facilities for composing a C++ program out of logical and physical parts. Chapters 6 Types and Declarations 7 read more..

  • Page - 149

    134 Basic Facilities Part II ‘‘... I have long entertained a suspicion, with regard to the decisions of philosophers upon all subjects, and found in myself a greater inclination to dispute, than assent to their conclusions. There is one mistake, to which they seem liable, almost without exception; they confine too much their principles, and make no account of that vast read more..

  • Page - 150

    6 Types and Declarations Perfection is achieved only on the point of collapse. – C. N. Parkinson • The ISO C++ Standard Implementations; The Basic Source Character Set • Types Fundamental Types; Booleans; Character Types; Integer Types; Floating-Point Types; Pre- fixes and Suffixes; void ; Sizes; Alignment • Declarations The Structure of Declarations; Declaring Multiple Names; Names; read more..

  • Page - 151

    136 Types and Declarations Chapter 6 hardware features that cannot be expressed directly in C++ or require reliance on specific imple- mentation details. Many important things are deemed implementation-defined by the standard. This means that each implementation must provide a specific, well-defined behavior for a construct and that behav- ior must be documented. For example: unsigned read more..

  • Page - 152

    Section 6.1 The ISO C++ Standard 137 unspecified or implementation-defined rather than undefined. It is worth spending considerable time and effort to ensure that a program does not use some- thing deemed unspecified or undefined by the standard. In many cases, tools exist to help do this. 6.1.1 Implementations A C++ implementation can be either hosted or freestanding read more..

  • Page - 153

    138 Types and Declarations Chapter 6 6.2 Types Consider: x = y+f(2); For this to make sense in a C++ program, the names x , y , and f must be suitably declared. That is, the programmer must specify that entities named x , y , and f exist and that they are of types for which = (assignment), + (addition), and () (function call), respectively, are meaningful. Every name read more..

  • Page - 154

    Section 6.2.1 Fundamental Types 139 The Boolean, character, and integer types are collectively called integral types. The integral and floating-point types are collectively called arithmetic types. Enumerations and classes (Chapter 16) are called user-defined types because they must be defined by users rather than being available for use without previous declaration, the way fundamental read more..

  • Page - 155

    140 Types and Declarations Chapter 6 void f(int i) { bool b {i!=0}; // ... }; In arithmetic and logical expressions, bool s are converted to int s; integer arithmetic and logical operations are performed on the converted values. If the result needs to be converted back to bool , a 0 is converted to false and a nonzero value is converted to true . For example: bool a = read more..

  • Page - 156

    Section 6.2.3 Character Types 141 char , but these three names are still considered separate types. A char variable can hold a character of the implementation’s character set. For example: char ch = 'a'; Almost universally, a char has 8 bits so that it can hold one of 256 different values. Typically, the character set is a variant of ISO-646, for example ASCII, thus providing read more..

  • Page - 157

    142 Types and Declarations Chapter 6 Fortunately, the difference matters only for values outside the 0 to 127 range, and the most common characters are within that range. Values outside that range stored in a plain char can lead to subtle portability problems. See §6.2.3.1 if you need to use more than one type of char or if you store integers in char variables. Note that the character types read more..

  • Page - 158

    Section 6.2.3.1 Signed and Unsigned Characters 143 c = sc; // OK c = uc; // implementation-defined if plain chars are signed and if uc’s value is too large sc = uc; // implementation defined if uc’s value is too large uc = sc; // OK: conversion to unsigned sc = c; // implementation-defined if plain chars are unsigned and if c’s value is too large uc = c; // read more..

  • Page - 159

    144 Types and Declarations Chapter 6 hexadecimal digits). There is no limit to the number of hexadecimal digits in the sequence. A sequence of octal or hexadecimal digits is terminated by the first character that is not an octal digit or a hexadecimal digit, respectively. For example: Octal Hexadecimal Decimal ASCII '\6' '\x6' 6 ACK '\60' '\x30' 48 '0' '\137' '\x05f' 95 '_' This read more..

  • Page - 160

    Section 6.2.4 Integer Types 145 The unsigned integer types are ideal for uses that treat storage as a bit array. Using an unsigned instead of an int to gain one more bit to represent positive integers is almost never a good idea. Attempts to ensure that some values are positive by declaring variables unsigned will typically be defeated by the implicit conversion rules read more..

  • Page - 161

    146 Types and Declarations Chapter 6 If no suffix is provided, the compiler gives an integer literal a suitable type based on its value and the implementation’s integer sizes (§6.2.4.2). It is a good idea to limit the use of nonobvious constants to a few well-commented const (§7.5), constexpr (§10.4), and enumerator (§8.4) initializers. 6.2.4.2 Types of Integer Literals In general, read more..

  • Page - 162

    Section 6.2.5.1 Floating-Point Literals 147 1.23 .23 0.23 1. 1.0 1.2e10 1.23e 15 Note that a space cannot occur in the middle of a floating-point literal. For example, 65.43 e 21 is not a floating-point literal but rather four separate lexical tokens (causing a syntax error): 65.43 e 21 If you want a floating-point literal of type oat , you can define one using the read more..

  • Page - 163

    148 Types and Declarations Chapter 6 1LU // unsigned long 2UL // unsigned long 3ULL // unsigned long long 4LLU // unsigned long long 5LUL // error The suffixes l and L can be used for floating-point literals to express long double . For example: 1L // long int 1.0L // long double Combinations of R , L , and u prefixes are allowed, for example, uR" read more..

  • Page - 164

    Section 6.2.8 Sizes 149 one. It is far easier to know and limit the impact of implementation dependencies when a program is written than to try to untangle the mess afterward. It is relatively easy to limit the impact of implementation-dependent language features. Limit- ing the impact of system-dependent library facilities is far harder. Using standard-library facilities wherever read more..

  • Page - 165

    150 Types and Declarations Chapter 6 In that last line, N can be char , short , int , long ,or long long . In addition, it is guaranteed that a char has at least 8 bits, a short at least 16 bits, and a long at least 32 bits. A char can hold a character of the machine’s character set. The char type is supposed to be chosen by the implementation to be the most read more..

  • Page - 166

    Section 6.2.9 Alignment 151 6.2.9 Alignment An object doesn’t just need enough storage to hold its representation. In addition, on some machine architectures, the bytes used to hold it must have proper alignment for the hardware to access it efficiently (or in extreme cases to access it at all). For example, a 4-byte int often has to be aligned on a word (4-byte) boundary, read more..

  • Page - 167

    152 Types and Declarations Chapter 6 struct Date { int d, m, y; }; int day(Date ∗ p) { return p >d; } double sqrt(double); template<class T> T abs(T a) { return a<0 ? a : a; } constexpr int fac(int n) { return (n<2)?1:n ∗fac(n 1); } // possible compile-time evaluation (§2.2.3) constexpr double zz { ii ∗fac(7) }; // compile-time initialization using Cmplx = read more..

  • Page - 168

    Section 6.3 Declarations 153 extern int error_number; extern short error_number; // error : type mismatch This has no errors (for the use of extern , see §15.2): extern int error_number; extern int error_number; // OK: redeclaration Some definitions explicitly specify a ‘‘value’’ for the entities they define. For example: struct Date { int d, m, y; }; using Point = read more..

  • Page - 169

    154 Types and Declarations Chapter 6 A declarator is composed of a name and optionally some declarator operators. The most com- mon declarator operators are: Declarator Operators prefix ∗ pointer prefix ∗const constant pointer prefix ∗volatile volatile pointer prefix & lvalue reference (§7.7.1) prefix && rvalue reference (§7.7.2) prefix auto function (using suffix return type) read more..

  • Page - 170

    Section 6.3.2 Declaring Multiple Names 155 Operators apply to individual names only – and not to any subsequent names in the same declara- tion. For example: int ∗ p, y; // int* p; int y; NOT int* y; int x, ∗q; // int x; int* q; int v[10], ∗pv; // int v[10]; int* pv; Such declarations with multiple names and nontrivial declarators make a program harder to read and read more..

  • Page - 171

    156 Types and Declarations Chapter 6 Choose names to reflect the meaning of an entity rather than its implementation. For example, phone_book is better than number_vector ev en if the phone numbers happen to be stored in a vector (§4.4). Do not encode type information in a name (e.g., pcname for a name that’s a char ∗ or icount for a count that’s an int ) as is read more..

  • Page - 172

    Section 6.3.4 Scope 157 6.3.4 Scope A declaration introduces a name into a scope; that is, a name can be used only in a specific part of the program text. • Local scope: A name declared in a function (Chapter 12) or lambda (§11.4) is called a local name. Its scope extends from its point of declaration to the end of the block in which its de- claration occurs. A block read more..

  • Page - 173

    158 Types and Declarations Chapter 6 Hiding names is unavoidable when writing large programs. However, a human reader can easily fail to notice that a name has been hidden (also known as shadowed). Because such errors are rela- tively rare, they can be very difficult to find. Consequently, name hiding should be minimized. Using names such as i and x for global variables read more..

  • Page - 174

    Section 6.3.4 Scope 159 This is an error because x is defined twice in the same scope. Names introduced in a for -statement are local to that statement (in statement scope). This allows us to use conventional names for loop variables repeatedly in a function. For example: void f(vector<string>& v, list<int>& lst) { for (const auto& x : v) cout << x << read more..

  • Page - 175

    160 Types and Declarations Chapter 6 int x3 {val}; // error : possible truncation char c3 {val2}; // error : possible narrowing char c4 {24}; // OK: 24 can be represented exactly as a char char c5 {264}; // error (assuming 8-bit chars): 264 cannot be represented as a char int x4 {2.0}; // error : no double to int value conversion // ... } See §10.5 for the conversion rules read more..

  • Page - 176

    Section 6.3.5 Initialization 161 • Arrays: §7.3.1, §7.3.2 • Constants: §10.4 • Classes: §17.3.1 (not using constructors), §17.3.2 (using constructors), §17.3.3 (default), §17.4 (member and base), §17.5 (copy and move) • User-defined containers: §17.3.4 6.3.5.1 Missing Initializers For many types, including all built-in types, it is possible to leave out the initializer. If you do that – and read more..

  • Page - 177

    162 Types and Declarations Chapter 6 If you want initialization of local variables of built-in type or objects of built-in type created with new , use {} . For example: void ff() { int x {}; // x becomes 0 char buf[1024]{}; // buf[i] becomes 0 for all i int ∗ p {new int{10}}; // *p becomes 10 char ∗ q {new char[1024]{}}; // q[i] becomes 0 for all i // ... } A read more..

  • Page - 178

    Section 6.3.5.2 Initializer Lists 163 6.3.6 Deducing a Type: auto and decltype() The language provides two mechanisms for deducing a type from an expression: • auto for deducing a type of an object from its initializer; the type can be the type of a vari- able, a const ,ora constexpr . • decltype(expr) for deducing the type of something that is not a simple initializer, such read more..

  • Page - 179

    164 Types and Declarations Chapter 6 We can decorate a deduced type with specifiers and modifiers (§6.3.1), such as const and & (ref- erence; §7.7). For example: void f(vector<int>& v) { for (const auto& x : v) { // x is a const int& // ... } } Here, auto is determined by the element type of v , that is, int . Note that the type of an expression is read more..

  • Page - 180

    Section 6.3.6.2 auto and {} -lists 165 auto x0 {}; // error : cannot deduce a type auto x1 {1}; // list of int with one element auto x2 {1,2}; // list of int with two elements auto x3 {1,2,3}; // list of int with three elements The type of a homogeneous list of elements of type T is taken to be of type initializer_list<T> (§3.2.1.3, §11.3.3). In particular, the read more..

  • Page - 181

    166 Types and Declarations Chapter 6 lvalue can refer to a constant (§7.7). An lvalue that has not been declared const is often called a modifiable lvalue. This simple and low-level notion of an object should not be confused with the notions of class object and object of polymorphic type (§3.2.2, §20.3.2). 6.4.1 Lvalues and Rvalues To complement the notion of an lvalue, we read more..

  • Page - 182

    Section 6.4.2 Lifetimes of Objects 167 We can classify objects based on their lifetimes: • Automatic: Unless the programmer specifies otherwise (§12.1.8, §16.2.12), an object declared in a function is created when its definition is encountered and destroyed when its name goes out of scope. Such objects are sometimes called automatic objects. In a typical implementation, automatic read more..

  • Page - 183

    168 Types and Declarations Chapter 6 template<class T> class list { using value_type = T; // every container has a value_type // ... }; For good and bad, type aliases are synonyms for other types rather than distinct types. That is, an alias refers to the type for which it is an alias. For example: Pchar p1 = nullptr; // p1 is a char* char ∗ p3 = p1; // fine read more..

  • Page - 184

    Section 6.6 Advice 169 [6] Avoid ‘‘magic constants’’; §6.2.4.1. [7] Avoid unnecessary assumptions about the size of integers; §6.2.8. [8] Avoid unnecessary assumptions about the range and precision of floating-point types; §6.2.8. [9] Prefer plain char over signed char and unsigned char ; §6.2.3.1. [10] Beware of conversions between signed and unsigned types; §6.2.3.1. [11] Declare read more..

  • Page - 185

    This page intentionally left blank read more..

  • Page - 186

    7 Pointers, Arrays, and References The sublime and the ridiculous are often so nearly related that it is difficult to class them separately. – Thomas Paine • Introduction • Pointers void ∗; nullptr • Arrays Array Initializers; String Literals • Pointers into Arrays Navigating Arrays; Multidimensional Arrays; Passing Arrays • Pointers and const • Pointers and Ownership • References read more..

  • Page - 187

    172 Pointers, Arrays, and References Chapter 7 7.2 Pointers For a type T , T ∗ is the type ‘‘pointer to T .’’ That is, a variable of type T ∗ can hold the address of an object of type T . For example: char c = 'a'; char ∗ p = &c; // p holds the address of c; & is the address-of operator or graphically: &c 'a' p : c : The fundamental operation on read more..

  • Page - 188

    Section 7.2.1 void ∗ 173 A pointer to any type of object can be assigned to a variable of type void ∗, but a pointer to func- tion (§12.5) or a pointer to member (§20.6) cannot. In addition, a void ∗ can be assigned to another void ∗, void ∗s can be compared for equality and inequality, and a void ∗ can be explicitly converted to another type. Other operations would read more..

  • Page - 189

    174 Pointers, Arrays, and References Chapter 7 Before nullptr was introduced, zero (0) was used as a notation for the null pointer. For example: int ∗ x=0; // x gets the value nullptr No object is allocated with the address 0 , and 0 (the all-zeros bit pattern) is the most common repre- sentation of nullptr . Zero (0)isan int . Howev er, the standard conversions read more..

  • Page - 190

    Section 7.3 Arrays 175 An array can be allocated statically, on the stack, and on the free store (§6.4.2). For example: int a1[10]; // 10 ints in static storage void f() { int a2 [20]; // 20 ints on the stack int ∗p = new int[40]; // 40 ints on the free store // ... } The C++ built-in array is an inherently low-level facility that should primarily be used inside read more..

  • Page - 191

    176 Pointers, Arrays, and References Chapter 7 There is no built-in copy operation for arrays. You cannot initialize one array with another (not ev en of exactly the same type), and there is no array assignment: int v6[8] = v5; // error : can’t copy an array (cannot assign an int* to an array) v6 = v5; // error : no array assignment Similarly, you can’t pass read more..

  • Page - 192

    Section 7.3.2 String Literals 177 The memory holding "range error" will not go away after a call of error_message() . Whether two identical string literals are allocated as one array or as two is implementation- defined (§6.1). For example: const char ∗ p = "Heraclitus"; const char ∗ q = "Heraclitus"; void g() { if (p == q) cout << "one!\n"; read more..

  • Page - 193

    178 Pointers, Arrays, and References Chapter 7 representing character classes (§37.1.1). This is a convention shared by many programming lan- guages, so we can’t just change it. Therefore, when you write regular expressions for use with the standard regex library (Chapter 37), the fact that a backslash is an escape character becomes a notable source of errors. Consider how to read more..

  • Page - 194

    Section 7.3.2.2 Larger Character Sets 179 There are six kinds of character literals supporting Unicode (Unicode literals). This sounds excessive, but there are three major encodings of Unicode: UTF-8, UTF-16, and UTF-32. For each of these three alternatives, both raw and ‘‘ordinary’’ strings are supported. All three UTF encod- ings support all Unicode characters, so which you use read more..

  • Page - 195

    180 Pointers, Arrays, and References Chapter 7 int v[] = { 1, 2, 3, 4 }; int ∗ p1 = v; // pointer to initial element (implicit conversion) int ∗ p2 = &v[0]; // pointer to initial element int ∗ p3 = v+4; // pointer to one-beyond-last element or graphically: p1 p2 p3 1 2 3 4 v : Taking a pointer to the element one beyond the end of an array is guaranteed to read more..

  • Page - 196

    Section 7.4.1 Navigating Arrays 181 7.4.1 Navigating Arrays Efficient and elegant access to arrays (and similar data structures) is the key to many algorithms (see §4.5, Chapter 32). Access can be achieved either through a pointer to an array plus an index or through a pointer to an element. For example: void (char v[]) { for (int i = 0; v[i]!=0; ++i) use(v[i]); } void fp(char read more..

  • Page - 197

    182 Pointers, Arrays, and References Chapter 7 cout << vi << ' ' << &vi[1] << ' ' << &vi[1] &vi[0] << ' ' << b yte_diff(&vi[0],&vi[1]) << '\n'; cout << vs << ' ' << &vs[1] << ' ' << &vs[1] &vs[0] << ' ' << b yte_diff(&vs[0],&vs[1]) << '\n'; } This produced: 0x7fffaef0 0x7fffaef4 1 4 0x7fffaedc 0x7fffaede 1 read more..

  • Page - 198

    Section 7.4.1 Navigating Arrays 183 This array concept is inherently low-level. Most advantages of the built-in array and few of the dis- advantages can be obtained through the use of the standard-library container array (§8.2.4, §34.2.1). Some C++ implementations offer optional range checking for arrays. However, such checking can be quite expensive, so it is often used only as a read more..

  • Page - 199

    184 Pointers, Arrays, and References Chapter 7 7.4.3 Passing Arrays Arrays cannot directly be passed by value. Instead, an array is passed as a pointer to its first ele- ment. For example: void comp(double arg[10]) // arg is a double* { for (int i=0; i!=10; ++i) arg[i]+=99; } void f() { double a1[10]; double a2[5]; double a3[100]; comp(a1); comp(a2); // disaster! comp(a3); // uses read more..

  • Page - 200

    Section 7.4.3 Passing Arrays 185 A matrix represented as a multidimensional array is passed as a pointer (rather than copied; §7.4). The first dimension of an array is irrelevant to finding the location of an element; it simply states how many elements (here, 3 ) of the appropriate type (here, int[5] ) are present. For example, look at the layout of ma above and note read more..

  • Page - 201

    186 Pointers, Arrays, and References Chapter 7 print_m35(v); print_mi5(v,3); print_mij(&v[0][0],3,5); } Note the use of &v[0][0] for the last call; v[0] would do because it is equivalent, but v would be a type error. This kind of subtle and messy code is best hidden. If you must deal directly with multi- dimensional arrays, consider encapsulating the code relying on it. In read more..

  • Page - 202

    Section 7.5 Pointers and const 187 void h() { Xval; // val can be modified here g(&val); // ... } When using a pointer, two objects are involved: the pointer itself and the object pointed to. ‘‘Pre- fixing’’ a declaration of a pointer with const makes the object, but not the pointer, a constant. To declare a pointer itself, rather than the object pointed to, to read more..

  • Page - 203

    188 Pointers, Arrays, and References Chapter 7 void f4() { int a = 1; const int c = 2; const int ∗ p1 = &c; // OK const int ∗ p2 = &a; // OK int ∗ p3 = &c; // error : initialization of int* with const int* ∗p3 = 7; // tr y to change the value of c } It is possible, but typically unwise, to explicitly remove the restrictions on a pointer to read more..

  • Page - 204

    Section 7.7 References 189 7.7 References A pointer allows us to pass potentially large amounts of data around at low cost: instead of copying the data we simply pass its address as a pointer value. The type of the pointer determines what can be done to the data through the pointer. Using a pointer differs from using the name of an object in a few ways: • We use read more..

  • Page - 205

    190 Pointers, Arrays, and References Chapter 7 To reflect the lvalue/rvalue and const /non-const distinctions, there are three kinds of references: • lvalue references: to refer to objects whose value we want to change • const references: to refer to objects whose value we do not want to change (e.g., a constant) • rvalue references: to refer to objects whose value we do read more..

  • Page - 206

    Section 7.7.1 Lvalue References 191 1 ii : &ii pp : rr : In some cases, the compiler can optimize away a reference so that there is no object representing that reference at run time. Initialization of a reference is trivial when the initializer is an lvalue (an object whose address you can take; see §6.4). The initializer for a ‘‘plain’’ T& must be an lvalue of read more..

  • Page - 207

    192 Pointers, Arrays, and References Chapter 7 int next(int p) { return p+1; } void g() { int x = 1; increment(x); // x=2 x = next(x); // x=3 } The increment(x) notation doesn’t giv e a clue to the reader that x ’s value is being modified, the way x=next(x) does. Consequently, ‘‘plain’’ reference arguments should be used only where the name of the function read more..

  • Page - 208

    Section 7.7.1 Lvalue References 193 int main() // count the number of occurrences of each word on input { Map<string,int> buf; for (string s; cin>>s;) ++buf[s]; for (const auto& x : buf) cout << x. rst << ": " << x.second << '\n'; } Each time around, the input loop reads one word from the standard input stream cin into the string s (§4.3.2) and then read more..

  • Page - 209

    194 Pointers, Arrays, and References Chapter 7 string&& rr1 {f()}; // rvalue reference, fine: bind rr1 to rvalue (a temporar y) string&& rr2 {v ar}; // rvalue reference, error : var is an lvalue string&& rr3 {"Oxfo rd"}; // rr3 refers to a temporar y holding "Oxford" const string cr1& {"Harvard"}; // OK: make temporar y and bind to cr1 The read more..

  • Page - 210

    Section 7.7.2 Rvalue References 195 template<class T> class vector { // ... vector(const vector& r); // copy constr uctor (copy r’s representation) vector(vector&& r); // move constr uctor ("steal" representation from r) }; vector<string> s; vector<string> s2 {s}; // s is an lvalue, so use copy constr uctor vector<string> s3 {s+"tail"); // s+"tail" is an read more..

  • Page - 211

    196 Pointers, Arrays, and References Chapter 7 v.clear(); // make v empty swap(v.vector<int>{}); // make v empty v = {}; // make v empty } Rvalue references can also be used to provide perfect forwarding (§23.5.2.1, §35.5.1). All standard-library containers provide move constructors and move assignment (§31.3.2). Also, their operations that insert new elements, such as insert() and read more..

  • Page - 212

    Section 7.7.4 Pointers and References 197 void fp(char ∗ p) { while ( ∗p) cout << ++ ∗p; } void fr(char& r) { while (r) cout << ++r; // oops: increments the char referred to, not the reference // near-infinite loop! } void fr2(char& r) { char ∗ p = &r; // get a pointer to the object referred to while ( ∗p) cout << ++ ∗p; } Conversely, if you want to read more..

  • Page - 213

    198 Pointers, Arrays, and References Chapter 7 If you want a collection of something that refers to an object, you must use a pointer: int x, y; string& a1[] = {x, y}; // error : array of references string ∗ a2[] = {&x, &y}; // OK vector<string&> s1 = {x , y}; // error : vector of references vector<string ∗> s2 = {&x, &y}; // OK Once we leave read more..

  • Page - 214

    Section 7.8 Advice 199 7.8 Advice [1] Keep use of pointers simple and straightforward; §7.4.1. [2] Avoid nontrivial pointer arithmetic; §7.4. [3] Take care not to write beyond the bounds of an array; §7.4.1. [4] Avoid multidimensional arrays; define suitable containers instead; §7.4.2. [5] Use nullptr rather than 0 or NULL ; §7.2.2. [6] Use containers (e.g., vector , array , and read more..

  • Page - 215

    This page intentionally left blank read more..

  • Page - 216

    8 Structures, Unions, and Enumerations Form a more perfect Union. – The people • Introduction • Structures struct Layout; struct Names; Structures and Classes; Structures and Arrays; Type Equiv- alence; Plain Old Data; Fields • Unions Unions and Classes; Anonymous union s • Enumerations enum class es; Plain enum s; Unnamed enum s • Advice 8.1 Introduction The key to effective use read more..

  • Page - 217

    202 Structures, Unions, and Enumerations Chapter 8 8.2 Structures An array is an aggregate of elements of the same type. In its simplest form, a struct is an aggregate of elements of arbitrary types. For example: struct Address { const char ∗ name; // "Jim Dandy" int number; // 61 const char ∗ street; // "South St" const char ∗ town; // "New read more..

  • Page - 218

    Section 8.2 Structures 203 Alternatively, a struct can be passed by reference and accessed using the . (struct member access) operator: void print_addr2(const Address& r) { cout << r.name << '\n' << r.nu mber << ' ' << r.street << '\n' << r.to wn << '\n' << r.state[0] << r .state[1] << ' ' << r.zip << '\n'; } Argument passing is discussed in read more..

  • Page - 219

    204 Structures, Unions, and Enumerations Chapter 8 Readout on a machine with 4-byte int would be: hour : value : seq : In this case, as on many machines, siz eof(Readout) is 12 , and not 6 as one would naively expect from simply adding the sizes of the individual members. You can minimize wasted space by simply ordering members by size (largest member first). For example: struct read more..

  • Page - 220

    Section 8.2.2 struct Names 205 more) struct s to refer to each other, we can declare a name to be the name of a struct . For example: struct List; // struct name declaration: List to be defined later struct Link { Link ∗ pre; Link ∗ suc; List ∗ member_of; int data; }; struct List { Link ∗ head; }; Without the first declaration of List , use of the pointer type read more..

  • Page - 221

    206 Structures, Unions, and Enumerations Chapter 8 8.2.3 Structures and Classes A struct is simply a class where the members are public by default. So, a struct can have member functions (§2.3.2, Chapter 16). In particular, a struct can have constructors. For example: struct Points { vector<Point> elem;// must contain at least one Point Points(Point p0) { elem.push_back(p0);} Points(Point read more..

  • Page - 222

    Section 8.2.3 Structures and Classes 207 Address::Address(const string& n, int nu, const string& s, const string& t, const string& st, int z) // validate postal code :name{n}, number{nu}, street{s}, town{t} { if (st.size()!=2) error("State abbre viation should be two characters") state = {st[0],st[1]}; // store postal code as characters ostringstream ost; // an output string stream; see read more..

  • Page - 223

    208 Structures, Unions, and Enumerations Chapter 8 Array shift(Array a, Point p) { for (int i=0; i!=3; ++i) { a.elem[i].x += p.x; a.elem[i].y += p.y; } return a; } Array ax = shift(points2,{10,20}); The notation for Array is a bit primitive: Why i!=3 ? Why keep repeating .elem[i] ? Why just ele- ments of type Point ? The standard library provides std::array (§34.2.1) as a more complete read more..

  • Page - 224

    Section 8.2.4 Structures and Arrays 209 Array shift(Array a, Point p) { for (int i=0; i!=a.size(); ++i) { a[i].x += p.x; a[i].y += p.y; } return a; } Array ax = shift(points,{10,20}); The main advantages of std::array over a built-in array are that it is a proper object type (has assign- ment, etc.) and does not implicitly convert to a pointer to an individual element: ostream& read more..

  • Page - 225

    210 Structures, Unions, and Enumerations Chapter 8 8.2.5 Type Equivalence Tw o struct s are different types even when they hav e the same members. For example: struct S1 { int a; }; struct S2 { int a; }; S1 and S2 are two different types, so: S1 x; S2 y = x; // error : type mismatch A struct is also a different type from a type used as a member. For example: S1 read more..

  • Page - 226

    Section 8.2.6 Plain Old Data 211 optimizations where they don’t break any language guarantees. Formally (§iso.3.9, §iso.9), a POD object must be of •a standard layout type, and •a trivially copyable type, • a type with a trivial default constructor. A related concept is a trivial type, which is a type with • a trivial default constructor and • trivial copy and move read more..

  • Page - 227

    212 Structures, Unions, and Enumerations Chapter 8 template<typename T> void mycopy(T ∗ to, const T ∗ from, int count) { if (is_pod<T>::value) memcpy(to,from,count ∗sizeof(T)); else for (int i=0; i!=count; ++i) to[i]=from[i]; } The is_pod is a standard-library type property predicate (§35.4.1) defined in <type_traits> allowing us to ask the question ‘‘Is T a POD?’’ in our read more..

  • Page - 228

    Section 8.2.7 Fields 213 if (p >dirty) { // contents changed // copy to disk p >dirty = 0; } } Surprisingly, using fields to pack several variables into a single byte does not necessarily save space. It saves data space, but the size of the code needed to manipulate these variables increases on most machines. Programs have been known to shrink significantly when binary read more..

  • Page - 229

    214 Structures, Unions, and Enumerations Chapter 8 struct Entry { char ∗ name; Type t; Value v; // use v.s if t==str; use v.i if t==num }; void f(Entry ∗ p) { if (p >t == str) cout << p >v.s; // ... } To avoid errors, one can encapsulate a union so that the correspondence between a type field and access to the union members can be guaranteed (§8.3.2). Unions read more..

  • Page - 230

    Section 8.3.1 Unions and Classes 215 8.3.1 Unions and Classes Many nontrivial union s hav e a member that is much larger than the most frequently used members. Because the size of a union is at least as large as its largest member, space is wasted. This waste can often be eliminated by using a set of derived classes (§3.2.2, Chapter 20) instead of a union . Technically, a read more..

  • Page - 231

    216 Structures, Unions, and Enumerations Chapter 8 fortunate that U won’t compile. When needed, a user can define a class containing a union that properly handles union members with constructors, destructors, and assignments (§8.3.2). If desired, such a class can also prevent the error of writing one member and then reading another. It is possible to specify an in-class initializer read more..

  • Page - 232

    Section 8.3.2 Anonymous unions 217 The read-access functions can be defined like this: int Entry2::number() const { if (type!=Tag::number) throw Bad_entr y{}; return i; }; string Entry2::text() const { if (type!=Tag::text) throw Bad_entr y{}; return s; }; These access functions check the type tag, and if it is the one that correctly corresponds to the access we want, it returns a read more..

  • Page - 233

    218 Structures, Unions, and Enumerations Chapter 8 Entry2::operator=() . Assignment combines the complexities of reading and writing but is otherwise logically similar to the access functions: Entry2& Entr y2::operator=(const Entr y2& e) // necessar y because of the string var iant { if (type==Tag::text && e.type==Tag::text) { s=e.s; // usual string assignment return ∗this; } if read more..

  • Page - 234

    Section 8.4.1 enum class es 219 8.4.1 enum class es An enum class is a scoped and strongly typed enumeration. For example: enum class Traf c_light { red, yellow, green }; enum class Warning { green, yellow, orang e, red }; // fire alert lev els Warning a1 = 7; // error : no int->War ning conversion int a2 = green; // error : green not in scope int a3 = read more..

  • Page - 235

    220 Structures, Unions, and Enumerations Chapter 8 case Warning::red: // do something break; } } A human might notice that yellow was missing, and a compiler might issue a warning because only three out of four Warning values are handled. An enumerator can be initialized by a constant expression (§10.4) of integral type (§6.2.1). For example: enum class Printer_ ags { acknowledg e=1, read more..

  • Page - 236

    Section 8.4.1 enum class es 221 I defined operator|() and operator&() to be constexpr functions (§10.4, §12.1.6) because someone might want to use those operators in constant expressions. For example: void g(Printer_ ags x) { switch (x) { case Printer_ ags::acknowledg e: // ... break; case Printer_ ags::busy: // ... break; case Printer_ ags::out_of_black: // ... break; case Printer_ read more..

  • Page - 237

    222 Structures, Unions, and Enumerations Chapter 8 Each enumerator has an integer value. We can extract that value explicitly. For example: int i = static_cast<int>(Flag::y); // i becomes 2 char c = static_cast<char>(Flag::e); // c becomes 8 The notion of a range of values for an enumeration differs from the enumeration notion in the Pas- cal family of languages. However, read more..

  • Page - 238

    Section 8.4.2 Plain enum s 223 void f(Traf c_light x) { if (x == red) { /* ... */ } // OK (ouch!) if (x == Warning::red) { /* ... */ } // OK (ouch!) if (x == Traf c_light::red) { /* ... */ } // error : red is not a Traffic_light value } The compiler accepts the x==red , which is almost certainly a bug. The injection of names into an enclosing scope (as enum s, read more..

  • Page - 239

    224 Structures, Unions, and Enumerations Chapter 8 8.4.3 Unnamed enum s A plain enum can be unnamed. For example: enum { arrow_up=1, arrow_down, arrow_sideways }; We use that when all we need is a set of integer constants, rather than a type to use for variables. 8.5 Advice [1] When compactness of data is important, lay out structure data members with larger members before read more..

  • Page - 240

    9 Statements A pro grammer is a machine for turning caffeine into code. – A pro grammer • Introduction • Statement Summary • Declarations as Statements • Selection Statements if Statements; switch Statements; Declarations in Conditions • Iteration Statements Range-for Statements; for Statements; while Statements; do Statements; Loop exit • goto Statements • Comments and Indentation • read more..

  • Page - 241

    226 Statements Chapter 9 9.2 Statement Summary Here is a summary of C++ statements: statement: declaration expression opt ; { statement-list opt } try { statement-list opt } handler-list case constant-expression : statement default : statement break ; continue ; return expression opt ; goto identifier ; identifier : statement selection-statement iteration-statement selection-statement: if ( condition ) statement read more..

  • Page - 242

    Section 9.2 Statement Summary 227 A (possibly empty) sequence of statements within ‘‘curly braces’’ (i.e., { and } ) is called a block or a compound statement. A name declared in a block goes out of scope at the end of its block (§6.3.4). A declaration is a statement and there is no assignment statement or procedure-call statement; assignments and function calls are read more..

  • Page - 243

    228 Statements Chapter 9 to give it its desired value. Input variables are among the few reasonable examples of that: void input() { int buf[max]; int count = 0; for (int i; cin>>i;) { if (i<0) err or("unexpected negative value"); if (count==max) error("buffer over ow"); buf[count++] = i; } // ... } I assume that error() does not return; if it does, this code may read more..

  • Page - 244

    Section 9.4.1 if Statements 229 enum E1 { a, b }; enum class E2 { a, b }; void f(E1 x, E2 y) { if (x) // OK // ... if (y) // error : no conversion to bool // ... if (y==E2::a) // OK // ... } The logical operators && || ! are most commonly used in conditions. The operators && and || will not evaluate their second argu- ment unless doing so is necessary. read more..

  • Page - 245

    230 Statements Chapter 9 void f1(int i) { if (i) int x = i+2; // error : declaration of if-statement branch } 9.4.2 switch Statements A switch -statement selects among a set of alternatives (case-labels). The expression in the case labels must be a constant expression of integral or enumeration type. A value may not be used more than once for case -labels in a switch -statement. read more..

  • Page - 246

    Section 9.4.2 switch Statements 231 Beware that a case of a switch must be terminated somehow unless you want to carry on execut- ing the next case. Consider: switch (val) { // beware case 1: cout << "case 1\n"; case 2: cout << "case 2\n"; default: cout << "default: case not found\n"; } Invoked with val==1 , the output will greatly surprise the read more..

  • Page - 247

    232 Statements Chapter 9 Such a mistake can easily occur when a new enumerator is added during maintenance. Testing for an ‘‘impossible’’ enumerator value is best done separately. 9.4.2.1 Declarations in Cases It is possible, and common, to declare variables within the block of a switch -statement. However, it is not possible to bypass an initialization. For example: void read more..

  • Page - 248

    Section 9.4.3 Declarations in Conditions 233 The obvious and traditional alternative is to declare d before the condition. However, this opens the scope (literally) for the use of d before its initialization or after its intended useful life: double d; // ... d2 = d; // oops! // ... if (d = prim(true)) { left /= d; break; } // ... d = 2.0; // two unrelated uses of d In read more..

  • Page - 249

    234 Statements Chapter 9 The for (int x : v) can be read as ‘‘for each element x in the range v ’’ or just ‘‘for each x in v .’’ The elements of v are visited in order from the first to the last. The scope of the variable naming the element (here, x )isthe for -statement. The expression after the colon must denote a sequence (a range); that is, it must read more..

  • Page - 250

    Section 9.5.2 for Statements 235 9.5.2 for Statements There is also a more general for -statement allowing greater control of the iteration. The loop vari- able, the termination condition, and the expression that updates the loop variable are explicitly pre- sented ‘‘up front’’ on a single line. For example: void f(int v[], int max) { for (int i = 0; i!=max; ++i) v[i] = i read more..

  • Page - 251

    236 Statements Chapter 9 However, many consider this idiom obscure and prefer to use: while(true) { // ‘‘forever’’ // ... } 9.5.3 while Statements A while -statement executes its controlled statement until its condition becomes false . For example: template<class Iter, class Value> Iter nd(Iter rst, Iter last, Value val) { while ( rst!=last && ∗ rst!=val) ++ rst; return read more..

  • Page - 252

    Section 9.5.5 Loop Exit 237 nearest enclosing switch-statement (§9.4.2) or iteration-statement. For example: void f(vector<string>& v, string terminator) { char c; string s; while (cin>>c) { // ... if (c == '\n') break; // ... } } We use a break when we need to leave the loop body ‘‘in the middle.’’ Unless it warps the logic of a loop (e.g., requires the read more..

  • Page - 253

    238 Statements Chapter 9 The scope of a label is the function it is in (§6.3.4). This implies that you can use goto to jump both into and out of blocks. The only restriction is that you cannot jump past an initializer or into an exception handler (§13.5). One of the few sensible uses of goto in ordinary code is to break out from a nested loop or switch -statement read more..

  • Page - 254

    Section 9.7 Comments and Indentation 239 // don’t use function "weird()" // function "f(int ...)" takes tw o or three arguments Such comments can typically be rendered unnecessary by proper use of C++. Once something has been stated clearly in the language, it should not be mentioned a second time in a comment. For example: a = b+c; // a becomes b+c count++; // read more..

  • Page - 255

    240 Statements Chapter 9 Note that / ∗∗/ style comments do not nest. For example: /* remove expensive check if (check(p,q)) error("bad p q") /* should never happen */ ∗/ This nesting should give an error for an unmatched final ∗/. 9.8 Advice [1] Don’t declare a variable until you have a value to initialize it with; §9.3, §9.4.3, §9.5.2. [2] Prefer a switch read more..

  • Page - 256

    10 Expressions Programming is like sex: It may give some concrete results, but that is not why we do it. – apologies to Richard Feynman • Introduction • A Desk Calculator The Parser; Input; Low-Level Input; Error Handling; The Driver; Headers; Command-Line Arguments; A Note on Style • Operator Summary Results; Order of Evaluation; Operator Precedence; Temporary Objects • Constant read more..

  • Page - 257

    242 Expressions Chapter 10 10.2 A Desk Calculator Consider a simple desk calculator program that provides the four standard arithmetic operations as infix operators on floating-point numbers. The user can also define variables. For example, given the input r=2.5 area = pi ∗ r ∗ r (pi is predefined) the calculator program will write 2.5 19.635 where 2.5 is the result of the read more..

  • Page - 258

    Section 10.2.1 The Parser 243 In other words, a program is a sequence of expressions separated by semicolons. The basic units of an expression are numbers, names, and the operators ∗, / , + , (both unary and binary), and = (assignment). Names need not be declared before use. I use a style of syntax analysis called recursive descent; it is a popular and straightforward top- read more..

  • Page - 259

    244 Expressions Chapter 10 expression and returns the value. The function expr() handles addition and subtraction. It consists of a single loop that looks for terms to add or subtract: double expr(bool get) // add and subtract { double left = term(get); for (;;) { // ‘‘forever’’ switch (ts.current().kind) { case Kind::plus: left += term(true); break; case Kind::minus: left = read more..

  • Page - 260

    Section 10.2.1 The Parser 245 The function term() handles multiplication and division in the same way expr() handles addition and subtraction: double term(bool get) // multiply and divide { double left = prim(get); for (;;) { switch (ts.current().kind) { case Kind::mul: left ∗= prim(true); break; case Kind::div: if (auto d = prim(true)) { left /= d; break; } return error("divide by read more..

  • Page - 261

    246 Expressions Chapter 10 case Kind::minus: // unar y minus return prim(true); case Kind::lp: { auto e = expr(true); if (ts.current().kind != Kind::rp) return error("')' expected"); ts.get(); // eat ’)’ return e; } default: return error("primar y expected"); } } When a Token that is a number (that is, an integer or floating-point literal) is seen, its value is placed in read more..

  • Page - 262

    Section 10.2.2 Input 247 10.2.2 Input Reading input is often the messiest part of a program. To communicate with a person, the program must cope with that person’s whims, conventions, and seemingly random errors. Trying to force the person to behave in a manner more suitable for the machine is often (rightly) considered offen- sive. The task of a low-level input routine is read more..

  • Page - 263

    248 Expressions Chapter 10 The initial statements read the first non-whitespace character from ∗ip (the stream pointed to by ip ) into ch and check that the read operation succeeded: Token Token_stream::g et() { char ch = 0; ∗ip>>ch; switch (ch) { case 0: return ct={Kind::end}; // assign and return By default, operator >> skips whitespace (that is, spaces, tabs, newlines, read more..

  • Page - 264

    Section 10.2.2 Input 249 ip >putback(ch); // put the first digit (or .) back into the input stream ∗ip >> ct.n umber_value; // read the number into ct ct.kind=Kind::number; return ct; Stacking case labels horizontally rather than vertically is generally not a good idea because this arrangement is harder to read. However, having one line for each digit is tedious. Because read more..

  • Page - 265

    250 Expressions Chapter 10 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': ip >putback(ch); // put the first digit (or .) back into the input stream ∗ip >> ct.n umber_value; // read number into ct ct.kind=Kind::number; return ct; default: // name, name =, or error if (isalpha(ch)) { ip >putback(ch); // put read more..

  • Page - 266

    Section 10.2.3 Low-Level Input 251 The standard-library function isspace() provides the standard test for whitespace (§36.2.1); isspace(c) returns a nonzero value if c is a whitespace character and zero otherwise. The test is implemented as a table lookup, so using isspace() is much faster than testing for the individual whitespace characters. Similar functions test if a character is a read more..

  • Page - 267

    252 Expressions Chapter 10 kept track of the line numbers, error() could have informed the user approximately where the error occurred. This would be useful when the calculator is used noninteractively. A more stylized and general error-handling strategy would separate error detection from error recovery. This can be implemented using exceptions (see §2.4.3.1, Chapter 13), b ut what we read more..

  • Page - 268

    Section 10.2.6 Headers 253 10.2.6 Headers The calculator uses standard-library facilities. Therefore, appropriate headers must be #include dto complete the program: #include<iostream> // I/O #include<string> // strings #include<map> // map #include<cctype> // isalpha(), etc. All of these headers provide facilities in the std namespace, so to use the names they provide we must either read more..

  • Page - 269

    254 Expressions Chapter 10 Token_stream ts {cin}; int main(int argc, char ∗ argv[]) { switch (argc) { case 1: // read from standard input break; case 2: // read from argument string ts.set_input(new istringstream{argv[1]}); break; default: error("too man y arguments"); return 1; } table["pi"] = 3.1415926535897932385; // inser t predefined names table["e"] = 2.7182818284590452354; read more..

  • Page - 270

    Section 10.2.8 A Note on Style 255 programmer could afford for a handcrafted piece of code to be used in just one program. Looking at the code for the calculator, especially at the first version, we can see that there isn’t much traditional C-style, low-level code presented. Many of the traditional tricky details have been replaced by uses of standard-library classes such read more..

  • Page - 271

    256 Expressions Chapter 10 Operator Summary (continued, continues) Member selection object . member §16.2.3 Member selection pointer > member §16.2.3 Subscripting pointer [ expr ] §7.3 Function call expr ( expr-list ) §12.2 Value construction type { expr-list } §11.3.2 Function-style type conversion type ( expr-list ) §11.5.4 Post increment lvalue ++ §11.1.4 Post decrement lvalue §11.1.4 Type read more..

  • Page - 272

    Section 10.3 Operator Summary 257 Operator Summary (continued) Multiply expr ∗ expr §10.2.1 Divide expr / expr §10.2.1 Modulo (remainder) expr % expr §10.2.1 Add (plus) expr + expr §10.2.1 Subtract (minus) expr expr §10.2.1 Shift left expr << expr §11.1.2 Shift right expr >> expr §11.1.2 Less than expr < expr §2.2.2 Less than or equal expr <= expr §2.2.2 Greater than expr > read more..

  • Page - 273

    258 Expressions Chapter 10 Before applying the grammar rules, lexical tokens are composed from characters. The longest possible sequence of characters is chosen to make a token. For example, && is a single operator, rather than two & operators, and a+++1 means (a ++) + 1 . This is sometimes called the Max Munch rule. Token Summary (§iso.2.7) Token Class Examples Reference read more..

  • Page - 274

    Section 10.3.1 Results 259 The relational operators, == , <= , etc., produce Boolean results. The meaning and result type of user-defined operators are determined by their declarations (§18.2). Where logically feasible, the result of an operator that takes an lvalue operand is an lvalue denoting that lvalue operand. For example: void f(int x, int y) { int j = x = y; // the read more..

  • Page - 275

    260 Expressions Chapter 10 operator that makes it well defined, such as ++ and += , or explicitly express sequencing using , (comma), && ,or || . The operators , (comma), && (logical and), and || (logical or) guarantee that their left-hand oper- and is evaluated before their right-hand operand. For example, b=(a=2,a+1) assigns 3 to b . Exam- ples of the use of || read more..

  • Page - 276

    Section 10.3.3 Operator Precedence 261 if (0 <= x <= 99) // ... This is legal, but it is interpreted as (0<=x)<=99 , where the result of the first comparison is either true or false . This Boolean value is then implicitly converted to 1 or 0 , which is then compared to 99 , yielding true . To test whether x is in the range 0..99 , we might use if (0<=x read more..

  • Page - 277

    262 Expressions Chapter 10 The problem with the if -statement is a bit more subtle. The condition will work as expected because the full expression in which the temporary holding s2+s3 is created is the condition itself. However, that temporary is destroyed before the controlled statement is entered, so any use of cs there is not guaranteed to work. Please note that in this read more..

  • Page - 278

    Section 10.4 Constant Expressions 263 primary role is to specify immutability in interfaces. This section is primarily concerned with the first role: compile-time evaluation. A constant expression is an expression that a compiler can evaluate. It cannot use values that are not known at compile time and it cannot have side effects. Ultimately, a constant expression must start out read more..

  • Page - 279

    264 Expressions Chapter 10 The expressive power of constant expressions is great. We can use integer, floating-point, and enumeration values. We can use any operator that doesn’t modify state (e.g., + , ?: , and [] , but not = or ++ ). We can use constexpr functions (§12.1.6) and literal types (§10.4.3) to provide a significant level of type safety and expressive power. It read more..

  • Page - 280

    Section 10.4.2 const s in Constant Expressions 265 const int x = 7; const string s = "asdf"; const int y = sqrt(x); A const initialized with a constant expression can be used in a constant expression. A const differs from a constexpr in that it can be initialized by something that is not a constant expression; in that case, the const cannot be used as a constant read more..

  • Page - 281

    266 Expressions Chapter 10 constexpr int radial_distance(Point p) { return isqrt(square(p.x)+square(p.y)+square(p.z)); } constexpr Point p1 {10,20,30}; // the default constructor is constexpr constexpr p2 {p1.up(20)}; // Point::up() is constexpr constexpr int dist = radial_distance(p2); I used int rather than double just because I didn’t hav e a constexpr floating-point square root func- tion handy. read more..

  • Page - 282

    Section 10.4.4 Reference Arguments 267 The copy constructor works because the compiler recognizes that the reference (the const com- plex< oat>& ) refers to a constant value and we just use that value (rather than trying anything advanced or silly with references or pointers). Literal types allow for type-rich compile-time programming. Traditionally, C++ compile-time evaluation has read more..

  • Page - 283

    268 Expressions Chapter 10 • A bit-field (§8.2.7) is converted to an int if int can represent all the values of the bit-field; otherwise, it is converted to unsigned int if unsigned int can represent all the values of the bit-field. Otherwise, no integral promotion applies to it. •A bool is converted to an int ; false becomes 0 and true becomes 1 . Promotions are used as part read more..

  • Page - 284

    Section 10.5.2.2 Floating-Point Conversions 269 10.5.2.2 Floating-Point Conversions A floating-point value can be converted to another floating-point type. If the source value can be exactly represented in the destination type, the result is the original numeric value. If the source value is between two adjacent destination values, the result is one of those values. Otherwise, the read more..

  • Page - 285

    270 Expressions Chapter 10 The pointer-to-bool conversion is useful in conditions, but confusing elsewhere: void (int); void fb(bool); void ff(int ∗ p, int ∗ q) { if (p) do_something( ∗p); // OK if (q!=nullptr) do_something( ∗q); // OK, but verbose // ... (p); // error : no pointer to int conversion fb(p); // OK: pointer to bool conversion (surpr ise!?) } Hope for a compiler read more..

  • Page - 286

    Section 10.5.2.6 Floating-Integral Conversions 271 A more general technique for expressing checked conversions is presented in §25.2.5.1. To truncate in a way that is guaranteed to be portable requires the use of numeric_limits (§40.2). In initializations, truncation can be avoided by using the {} -initializer notation (§6.3.5). 10.5.3 Usual Arithmetic Conversions These conversions are read more..

  • Page - 287

    This page intentionally left blank read more..

  • Page - 288

    11 Select Operations When someone says “I want a programming language in which I need only say what I wish done,” give him a lollipop. – Alan Perlis • Etc. Operators Logical Operators; Bitwise Logical Operators; Conditional Expressions; Increment and Decrement • Free Store Memory Management; Arrays; Getting Memory Space; Overloading new • Lists Implementation Model; Qualified Lists; read more..

  • Page - 289

    274 Select Operations Chapter 11 11.1.1 Logical Operators The logical operators && (and), || (or), and ! (not) take operands of arithmetic and pointer types, convert them to bool , and return a bool result. The && and || operators evaluate their second argu- ment only if necessary, so they can be used to control evaluation order (§10.3.2). For example: while (p read more..

  • Page - 290

    Section 11.1.2 Bitwise Logical Operators 275 Please note that this bit fiddling is taken from the implementation of iostreams rather than from the user interface. Convenient bit manipulation can be very important, but for reliability, maintain- ability, portability, etc., it should be kept at low lev els of a system. For more general notions of a set, see the standard-library set read more..

  • Page - 291

    276 Select Operations Chapter 11 11.1.4 Increment and Decrement The ++ operator is used to express incrementing directly, rather than expressing it indirectly using a combination of an addition and an assignment. Provided lvalue has no side effects, ++lvalue means lvalue+=1 , which again means lvalue=lvalue+1 . The expression denoting the object to be incre- mented is evaluated once read more..

  • Page - 292

    Section 11.1.4 Increment and Decrement 277 while ( ∗q!=0){ ∗p++ = ∗q++; } ∗p=0; // terminating zero The value of ∗p++ = ∗q++ is ∗q. We can therefore rewrite the example like this: while (( ∗p++ = ∗q++) != 0) { } In this case, we don’t notice that ∗q is zero until we already have copied it into ∗p and incremented p . Consequently, we can eliminate the read more..

  • Page - 293

    278 Select Operations Chapter 11 Enode ∗ expr(bool get) { Enode ∗ left = term(get); for (;;) { switch (ts.current().kind) { case Kind::plus: case Kind::minus: left = new Enode {ts.current().kind,left,term(true)}; break; default: return left; // return node } } } In cases Kind::plus and Kind::minus ,anew Enode is created on the free store and initialized by the value read more..

  • Page - 294

    Section 11.2 Free Store 279 The delete operator may be applied only to a pointer returned by new or to the nullptr . Applying delete to the nullptr has no effect. If the deleted object is of a class with a destructor (§3.2.1.2, §17.2), that destructor is called by delete before the object’s memory is released for reuse. 11.2.1 Memory Management The main problems with free read more..

  • Page - 295

    280 Select Operations Chapter 11 As alternatives to using ‘‘naked’’ new s and delete s, I can recommend two general approaches to resource management that avoid such problems: [1] Don’t put objects on the free store if you don’t hav e to; prefer scoped variables. [2] When you construct an object on the free store, place its pointer into a manager object (sometimes read more..

  • Page - 296

    Section 11.2.1 Memory Management 281 // ... if (n%2) throw runtime_error("odd"); delete[] p1; // we may nev er get here } For f(3) the memory pointed to by p1 is leaked, but the memory pointed to by p2 is correctly and implicitly deallocated. My rule of thumb for the use of new and delete is ‘‘no naked new s’’; that is, new belongs in con- structors and similar read more..

  • Page - 297

    282 Select Operations Chapter 11 To deallocate space allocated by new , delete and delete[] must be able to determine the size of the object allocated. This implies that an object allocated using the standard implementation of new will occupy slightly more space than a static object. At a minimum, space is needed to hold the object’s size. Usually two or more words per read more..

  • Page - 298

    Section 11.2.3 Getting Memory Space 283 void ∗ operator new[](siz e_t); // allocate space for array void operator delete[](void ∗ p); // if (p) deallocate space allocated using operator new[]() When operator new needs to allocate space for an object, it calls operator new() to allocate a suitable number of bytes. Similarly, when operator new needs to allocate space for an array, read more..

  • Page - 299

    284 Select Operations Chapter 11 We can place objects anywhere by providing an allocator function (§11.2.3) with e xtra arguments and then supplying such extra arguments when using new : void ∗ operator new(siz e_t, void ∗ p) { return p; } // explicit placement operator void ∗ buf = reinterpret_cast<void ∗>(0xF00F); // significant address X ∗ p2 = new(buf) X; // construct read more..

  • Page - 300

    Section 11.2.4 Overloading new 285 Placing an object in an area that is not (directly) controlled by the standard free-store manager implies that some care is required when destroying the object. The basic mechanism for that is an explicit call of a destructor: void destroy(X ∗ p, Arena ∗ a) { p >˜X(); // call destructor a >free(p); // free memory } Note that explicit calls read more..

  • Page - 301

    286 Select Operations Chapter 11 11.3 Lists In addition to their use for initializing named variables (§6.3.5.2), {} -lists can be used as expressions in many (but not all) places. They can appear in two forms: [1] Qualified by a type, T{ ...}, meaning ‘‘create an object of type T initialized by T{ ...}’’; §11.3.2 [2] Unqualified { ...}, for which the the type must be read more..

  • Page - 302

    Section 11.3.1 Implementation Model 287 {1,2,3.14} is interpreted as a temporary constructed and used like this: const double temp[] = {double{1}, double{2}, 3.14 } ; const initializer_list<double> tmp(temp,sizeof(temp)/siz eof(double)); vector<double> v(tmp); That is, the compiler constructs an array containing the initializers converted to the desired type (here, double ). This array is passed read more..

  • Page - 303

    288 Select Operations Chapter 11 One way of looking at a qualified initializer list with one element is as a conversion from one type to another. For example: template<class T> T square(T x) { return x ∗x; } void f(int i) { double d = square(double{i}); complex<double> z = square(complex<double>{i}); } That idea is explored further in §11.5.1. 11.3.3 Unqualified Lists A read more..

  • Page - 304

    Section 11.3.3 Unqualified Lists 289 The standard-library type initializer_list<T> is used to handle variable-length {} -lists (§12.2.3). Its most obvious use is to allow initializer lists for user-defined containers (§3.2.1.3), b ut it can also be used directly; for example: int high_value(initializ er_list<int> val) { int high = numeric_traits<int>lowest(); if (val.siz e()==0) read more..

  • Page - 305

    290 Select Operations Chapter 11 This too is unfortunate, but it is a bit more understandable from a language-technical point of view: nowhere in those calls does it say vector . To deduce T the compiler would first have to decide that the user really wanted a vector and then look into the definition of vector to see if it has a construc- tor that accepts {1,2,3} . read more..

  • Page - 306

    Section 11.4.1 Implementation Model 291 void print_modulo(const vector<int>& v, ostream& os, int m) // output v[i] to os if v[i]%m==0 { for_each(begin(v),end(v), [&os,m](int x) { if (x%m==0) os << x << '\n'; } ); } To see what this means, we can define the equivalent function object: class Modulo_print { ostream& os; // members to hold the capture list int m; public: read more..

  • Page - 307

    292 Select Operations Chapter 11 void print_modulo(const vector<int>& v, ostream& os, int m) // output v[i] to os if v[i]%m==0 { class Modulo_print { ostream& os; // members to hold the capture list int m; public: Modulo_print (ostream& s, int mm) :os(s), m(mm) {} // capture void operator()(int x) const { if (x%m==0) os << x << '\n'; } }; read more..

  • Page - 308

    Section 11.4.2 Alternatives to Lambdas 293 traversals easy and general. For example, using a for -statement to traverse a map gives a depth-first traversal. How would we do a breadth-first traversal? The for -loop version of print_modulo() is not amenable to change, so we have to rewrite it to an algorithm. For example: template<class C> void print_modulo(const C& v, ostream& read more..

  • Page - 309

    294 Select Operations Chapter 11 • [] : an empty capture list. This implies that no local names from the surrounding context can be used in the lambda body. For such lambda expressions, data is obtained from arguments or from nonlocal variables. • [&] : implicitly capture by reference. All local names can be used. All local variables are accessed by reference. • [=] : read more..

  • Page - 310

    Section 11.4.3 Capture 295 template<typename... Var> void algo(int s, Var... v) { auto helper = [&s,&v...] { return s ∗(h1(v...)+h2(v...)); } // ... } Beware that is it easy to get too clever about capture. Often, there is a choice between capture and argument passing. When that’s the case, capture is usually the least typing but has the greatest potential for confusion. read more..

  • Page - 311

    296 Select Operations Chapter 11 void print_all(const map<string,int>& m, const string& label) { cout << label << ":\n{\n"; for_each(m.begin(),m.end(), [](const pair<string,int>& p) { cout << p << '\n'; } ); cout << "}\n"; } Here, we don’t need to capture cout or the output operator for pair . 11.4.3.3 Lambda and this How do we access members of read more..

  • Page - 312

    Section 11.4.4 Call and Return 297 11.4.4 Call and Return The rules for passing arguments to a lambda are the same as for a function (§12.2), and so are the rules for returning results (§12.1.4). In fact, with the exception of the rules for capture (§11.4.3) most rules for lambdas are borrowed from the rules for functions and classes. However, two irregu- larities should be read more..

  • Page - 313

    298 Select Operations Chapter 11 rev(&s1[0],&s1[0]+s1.siz e()); rev(&s2[0],&s2[0]+s2.siz e()); } Now, the type of rev is specified before it is used. If we just want to name a lambda, rather than using it recursively, auto can simplify things: void g(vector<string>& vs1, vector<string>& vs2) { auto rev = [&](char ∗ b, char ∗ e) { while (1<e b) swap( read more..

  • Page - 314

    Section 11.5 Explicit Type Conversion 299 template<class T arget, class Source> Targ et narrow_cast(Source v) { auto r = static_cast<Target>(v); // convert the value to the target type if (static_cast<Source>(r)!=v) throw runtime_error("narrow_cast<>() failed"); return r; } That is, if I can convert a value to the target type, convert the result back to the source read more..

  • Page - 315

    300 Select Operations Chapter 11 void f(int); void f(double); void g(int i, double d) { f(i); // call f(int) f(double{i}); // error : {} doesn’t do int to floating conversion f(d); // call f(double) f(int{d}); // error : {} doesn’t truncate f(static_cast<int>(d)); // call f(int) with a truncated value f(round(d)); // call f(double) with a rounded value read more..

  • Page - 316

    Section 11.5.1 Construction 301 template<class T> void f(const T&); void g3() { f(int{}); // default int value f(complex<double>{}); // default complex value // ... } The value of an explicit use of the constructor for a built-in type is 0 converted to that type (§6.3.5). Thus, int{} is another way of writing 0 . For a user-defined type T , T{} is defined by the read more..

  • Page - 317

    302 Select Operations Chapter 11 • reinterpret_cast handles conversions between unrelated types such as an integer to a pointer or a pointer to an unrelated pointer type (§iso.5.2.10). • const_cast converts between types that differ only in const and volatile qualifiers (§iso.5.2.11). • dynamic_cast does run-time checked conversion of pointers and references into a class hier- archy read more..

  • Page - 318

    Section 11.5.4 Function-Style Cast 303 11.5.4 Function-Style Cast The construction of a value of type T from a value e can be expressed by the functional notation T(e) . For example: void f(double d) { int i = int(d); // truncate d complex z = complex(d); // make a complex from d // ... } The T(e) construct is sometimes referred to as a function-style cast. Unfortunately, for a read more..

  • Page - 319

    This page intentionally left blank read more..

  • Page - 320

    12 Functions Death to all fanatics! – Paradox • Function Declarations Why Functions?; Parts of a Function Declaration; Function Definitions; Returning Values; inline Functions; constexpr Functions; [[noreturn]] Functions; Local Variables • Argument Passing Reference Arguments; Array Arguments; List Arguments; Unspecified Number of Argu- ments; Default Arguments • Overloaded Functions Automatic Overload read more..

  • Page - 321

    306 Functions Chapter 12 The semantics of argument passing are identical to the semantics of copy initialization (§16.2.6). Argument types are checked and implicit argument type conversion takes place when necessary. For example: double s2 = sqrt(2); // call sqrt() with the argument double{2} double s3 = sqrt("three"); // error : sqr t() requires an argument of type double read more..

  • Page - 322

    Section 12.1.2 Parts of a Function Declaration 307 12.1.2 Parts of a Function Declaration In addition to specifying a name, a set of arguments, and a return type, a function declaration can contain a variety of specifiers and modifiers. In all we can have: • The name of the function; required • The argument list, which may be empty () ; required • The return type, read more..

  • Page - 323

    308 Functions Chapter 12 That function, f() , could be defined as: void f(int x) { /*we can modify x here */ } Alternatively, we could define f() as: void f(const int x) { /*we cannot modify x here */ } In either case, the argument that f() can or cannot modify is a copy of what a caller provided, so there is no danger of an obscure modification of the calling read more..

  • Page - 324

    Section 12.1.4 Returning Values 309 That is, a prefix auto indicates that the return type is placed after the argument list. The suffix return type is preceded by > . The essential use for a suffix return type comes in function template declarations in which the return type depends on the arguments. For example: template<class T , class U> auto product(const read more..

  • Page - 325

    310 Functions Chapter 12 int ∗ fp() { int local = 1; // ... return &local; // bad } An equivalent error can occur when using references: int& fr() { int local = 1; // ... return local; // bad } Fortunately, a compiler can easily warn about returning references to local variables (and most do). There are no void values. However, a call of a void function may be used read more..

  • Page - 326

    Section 12.1.5 inline Functions 311 The inline specifier is a hint to the compiler that it should attempt to generate code for a call of fac() inline rather than laying down the code for the function once and then calling through the usual function call mechanism. A clever compiler can generate the constant 720 for a call fac(6) . The possibility of mutually recursive inline read more..

  • Page - 327

    312 Functions Chapter 12 consist of a single return -statement; no loops and no local variables are allowed. Also, a constexpr function may not have side effects. That is, a constexpr function is a pure function. For example: int glob; constexpr void bad1(int a) // error : constexpr function cannot be void { glob = a; // error : side effect in constexpr function } constexpr read more..

  • Page - 328

    Section 12.1.6.1 constexpr and References 313 template<> class complex< oat> { public: // ... explicit constexpr complex(const complex<double>&); // ... }; This allows us to write: constexpr complex< oat> z {2.0}; The temporary variable that is logically constructed to hold the const reference argument simply becomes a value internal to the compiler. It is possible for a read more..

  • Page - 329

    314 Functions Chapter 12 12.1.7 [[noreturn]] Functions A construct [[ ...]] is called an attribute and can be placed just about anywhere in the C++ syntax. In general, an attribute specifies some implementation-dependent property about the syntactic entity that precedes it. In addition, an attribute can be placed in front of a declaration. There are only two standard attributes read more..

  • Page - 330

    Section 12.1.8 Local Variables 315 int fn(int n) { static int n1 = n; // OK static int n2 = fn(n 1)+1; // undefined return n; } A static local variable is useful for avoiding order dependencies among nonlocal variables (§15.4.1). There are no local functions; if you feel you need one, use a function object or a lambda expres- sion (§3.4.3, §11.4). The scope of a label read more..

  • Page - 331

    316 Functions Chapter 12 12.2.1 Reference Arguments Consider: void f(int val, int& ref) { ++val; ++ref; } When f() is called, ++val increments a local copy of the first actual argument, whereas ++ref incre- ments the second actual argument. Consider: void g() { int i = 1; int j = 1; f(i,j); } The call f(i,j) will increment j but not i . The first argument, i , is passed by read more..

  • Page - 332

    Section 12.2.1 Reference Arguments 317 exactly the same set of values as a T argument by passing the value in a temporary, if necessary. For example: oat fsqrt(const oat&); // Fortran-style sqrt taking a reference argument void g(double d) { oat r = fsqrt(2.0f); // pass reference to temp holding 2.0f r=fsqr t(r); // pass reference to r r=fsqr t(d); // pass reference to read more..

  • Page - 333

    318 Functions Chapter 12 How do we choose among the ways of passing arguments? My rules of thumb are: [1] Use pass-by-value for small objects. [2] Use pass-by-const-reference to pass large values that you don’t need to modify. [3] Return a result as a return value rather than modifying an object through an argument. [4] Use rvalue references to implement move (§3.3.2, §17.5.2) read more..

  • Page - 334

    Section 12.2.2 Array Arguments 319 void f(int(&r)[4]); void g() { int a1[] = {1,2,3,4}; int a2[] = {1,2}; f(a1); // OK f(a2); // error : wrong number of elements } Note that the number of elements is part of a reference-to-array type. That makes such references far less flexible than pointers and containers (such as vector ). The main use of references to arrays is in read more..

  • Page - 335

    320 Functions Chapter 12 template<class T> void f1(initializer_list<T>); struct S { int a; string s; }; void f2(S); template<class T , int N> void f3(T (&r)[N]); void f4(int); void g() { f1({1,2,3,4}); // T is int and the initializer_list has size() 4 f2({1,"MKS"}); // f2(S{1,"MKS"}) f3({1,2,3,4}); // T is int and N is 4 f4({1}); // f4(int{1}); } If there is read more..

  • Page - 336

    Section 12.2.3 List Arguments 321 If there is a function with an initializer-list argument in scope, but the argument list isn’t a match for that, another function can be chosen. The call f({1,"MKS"}) was an example of that. Note that these rules apply to std::initializer_list<T> arguments only. There are no special rules for std::initializer_list<T>& or for other read more..

  • Page - 337

    322 Functions Chapter 12 Clearly, if an argument has not been declared, the compiler does not have the information needed to perform the standard type checking and type conversion for it. In that case, a char or a short is passed as an int and a oat is passed as a double . This is not necessarily what the program- mer expects. A well-designed program needs at most a read more..

  • Page - 338

    Section 12.2.4 Unspecified Number of Arguments 323 The error() function could be defined like this: #include <cstdarg> void error(int severity ...) // ‘‘severity’’ followed by a zero-ter minated list of char*s { va_list ap; va_star t(ap,severity); // arg startup for (;;) { char ∗ p = va_arg(ap,char ∗); if (p == nullptr) break; cerr << p << ' '; } va_end(ap); // arg read more..

  • Page - 339

    324 Functions Chapter 12 The int -to-string conversion function to_string() is provided by the standard library (§36.3.5). If I didn’t hav e to mimic C style, I would further simplify the code by passing a container as a single argument: void error(int severity, const vector<string>& err) // almost as before { for (auto& s : err) cerr << s << ' '; cerr << read more..

  • Page - 340

    Section 12.2.5 Default Arguments 325 constructors do more work and the repetitiveness is common. We could deal with the repetitiveness by considering one of the constructors ‘‘the real one’ ’ and forward to that (§17.4.3): complex(double r, double i) :re{r}, im{i} {} // construct complex from two scalars complex(double r) :complex{2,0} {} // construct complex from one scalar read more..

  • Page - 341

    326 Functions Chapter 12 void g() { void f(int x = 9); // OK: this declaration hides the outer one // ... } Declaring a name in a nested scope so that the name hides a declaration of the same name in an outer scope is error-prone. 12.3 Overloaded Functions Most often, it is a good idea to give different functions different names, but when different func- tions read more..

  • Page - 342

    Section 12.3.1 Automatic Overload Resolution 327 To approximate our notions of what is reasonable, a series of criteria are tried in order: [1] Exact match; that is, match using no or only trivial conversions (for example, array name to pointer, function name to pointer to function, and T to const T ) [2] Match using promotions; that is, integral promotions (bool to int , read more..

  • Page - 343

    328 Functions Chapter 12 void print_int(int); void print_char(char); void print_string(const char ∗); // C-style string void g(int i, char c, const char ∗ p, double d) { print_int(i); // OK print_char(c); // OK print_string(p); // OK print_int(c); // OK? calls print_int(int(c)), prints a number print_char(i); // OK? calls print_char(char(i)), narrowing print_string(i); // error print_int(d); // read more..

  • Page - 344

    Section 12.3.3 Overloading and Scope 329 void f(int); void g() { void f(double); f(1); // call f(double) } Clearly, f(int) would have been the best match for f(1) , but only f(double) is in scope. In such cases, local declarations can be added or subtracted to get the desired behavior. As always, intentional hiding can be a useful technique, but unintentional hiding is a source read more..

  • Page - 345

    330 Functions Chapter 12 In the process of choosing among overloaded functions with two or more arguments, a best match is found for each argument using the rules from §12.3. A function that is the best match for one argument and a better or equal match for all other arguments is called. If no such function exists, the call is rejected as ambiguous. For example: void read more..

  • Page - 346

    Section 12.4 Pre- and Postconditions 331 argument values. The compiler and linker can ensure that arguments are of the right types, but it is up to the programmer to decide what to do about ‘‘bad’’ argument values. We call logical criteria that are supposed to hold when a function is called preconditions, and logical criteria that are sup- posed to hold when a read more..

  • Page - 347

    332 Functions Chapter 12 The writer of a function has several alternatives, including: [1] Make sure that every input has a valid result (so that we don’t hav e a precondition). [2] Assume that the precondition holds (rely on the caller not to make mistakes). [3] Check that the precondition holds and throw an exception if it does not. [4] Check that the precondition read more..

  • Page - 348

    Section 12.5 Pointer to Function 333 void f() { pf = &f1; // OK pf = &f2; // error : bad return type pf = &f3; // error : bad argument type pf("Hera"); // OK pf(1); // error : bad argument type int i = pf("Zeus"); // error : void assigned to int } The rules for argument passing are the same for calls directly to a function and for calls to read more..

  • Page - 349

    334 Functions Chapter 12 { for (int gap=n/2; 0<gap; gap/=2) for (int i=gap; i!=n; i++) for (int j=i gap; 0<=j; j =gap) { char ∗ b = static_cast<char ∗>(base); // necessar y cast char ∗ pj = b+j ∗sz; // &base[j] char ∗ pjg = b+(j+gap) ∗sz; // &base[j+gap] if (cmp(pjg,pj)<0) { // swap base[j] and base[j+gap]: for (int k=0; k!=sz; k++) { char temp = pj[k]; read more..

  • Page - 350

    Section 12.5 Pointer to Function 335 int cmp1(const void ∗ p, const void ∗ q) // Compare name strings { return strcmp(static_cast<const User ∗>(p) >name,static_cast<const User ∗>(q) >name); } int cmp2(const void ∗ p, const void ∗ q) // Compare dept numbers { return static_cast<const User ∗>(p) >dept static_cast<const User ∗>(q) >dept; } There is no read more..

  • Page - 351

    336 Functions Chapter 12 No mention of sizes is needed nor any helper functions. If the explicit use of begin() and end() is annoying, it can be eliminated by using a version of sort() that takes a container (§14.4.5): sort(heads,[](const User& x, const User& y) { return x.name<y .name; }); You can take the address of an overloaded function by assigning to or initializing a read more..

  • Page - 352

    Section 12.6 Macros 337 Where NAME is encountered as a token, it is replaced by rest of line . For example: named = NAME will expand into named = rest of line A macro can also be defined to take arguments. For example: #de ne MAC(x,y) argument1: x argument2: y When MAC is used, two argument strings must be presented. They will replace x and y when MAC() is expanded. For read more..

  • Page - 353

    338 Functions Chapter 12 If you must use a macro, use the scope resolution operator, :: , when referring to global names (§6.3.4) and enclose occurrences of a macro argument name in parentheses whenever possible. For example: #de ne MIN(a,b) (((a)<(b))?(a):(b)) This handles the simpler syntax problems (which are often caught by compilers), but not the prob- lems with side effects. For example: int read more..

  • Page - 354

    Section 12.6 Macros 339 void f() { printx(a); // cout << "a" << " = " << a << '\n'; printx(str); // cout << "str" << " = " << str << '\n'; } Writing #x " = " rather than #x << " = " is obscure ‘‘clever code’’ rather than an error. Adjacent string literals are concatenated (§7.3.2). The read more..

  • Page - 355

    340 Functions Chapter 12 Most uses of #ifdef are less bizarre, and when used with restraint, #ifdef and its complement #ifn- def do little harm. See also §15.3.3. Names of the macros used to control #ifdef should be chosen carefully so that they don’t clash with ordinary identifiers. For example: struct Call_info { Node ∗ arg_one; Node ∗ arg_two; // ... }; This innocent-looking read more..

  • Page - 356

    Section 12.6.3 Pragmas 341 12.6.3 Pragmas Implementations often provide facilities that differ from or go beyond what the standard offers. Obviously, the standard cannot specify how such facilities are provided, but one standard syntax is a line of tokens prefixed with the preprocessor directive #pragma . For example: #pragma foo bar 666 foobar If possible, #pragma s are best avoided. read more..

  • Page - 357

    This page intentionally left blank read more..

  • Page - 358

    13 Exception Handling Don’t interrupt me while I’m interrupting. – Winston S. Churchill • Error Handling Exceptions; Traditional Error Handling; Muddling Through; Alternative Views of Excep- tions; When You Can’t Use Exceptions; Hierarchical Error Handling; Exceptions and Effi- ciency • Exception Guarantees • Resource Management Finally • Enforcing Invariants • Throwing and Catching read more..

  • Page - 359

    344 Exception Handling Chapter 13 The discussion of errors focuses on errors that cannot be handled locally (within a single small function), so that they require separation of error-handling activities into different parts of a pro- gram. Such parts of a program are often separately developed. Consequently, I often refer to a part of a program that is invoked to perform a read more..

  • Page - 360

    Section 13.1.1 Exceptions 345 The taskmaster() asks do_task() to do a job. If do_task() can do that job and return a correct result, all is fine. Otherwise, do_task() must report a failure by throwing some exception. The taskmaster() is prepared to handle a Some_error , but some other kind of exception may be thrown. For example, do_task() may call other functions to do a lot read more..

  • Page - 361

    346 Exception Handling Chapter 13 • Terminate the program. This is a pretty drastic approach. For example: if (something_wrong) exit(1); For most errors, we can and must do better. For example, in most situations we should at least write out a decent error message or log the error before terminating. In particular, a library that doesn’t know about the purpose and general read more..

  • Page - 362

    Section 13.1.3 Muddling Through 347 13.1.3 Muddling Through One aspect of the exception-handling scheme that will appear novel to some programmers is that the ultimate response to an unhandled error (an uncaught exception) is to terminate the program. The traditional response has been to muddle through and hope for the best. Thus, exception han- dling makes programs more read more..

  • Page - 363

    348 Exception Handling Chapter 13 13.1.4.1 Asynchronous Events The mechanism is designed to handle only synchronous exceptions, such as array range checks and I/O errors. Asynchronous events, such as keyboard interrupts and power failures, are not necessar- ily exceptional and are not handled directly by this mechanism. Asynchronous events require mechanisms fundamentally different from read more..

  • Page - 364

    Section 13.1.5 When You Can’t Use Exceptions 349 13.1.5 When You Can’t Use Exceptions Use of exceptions is the only fully general and systematic way of dealing with errors in a C++ pro- gram. However, we must reluctantly conclude that there are programs that for practical and histori- cal reasons cannot use exceptions. For example: • A time-critical component of an embedded read more..

  • Page - 365

    350 Exception Handling Chapter 13 13.1.6 Hierarchical Error Handling The purpose of the exception-handling mechanisms is to provide a means for one part of a program to inform another part that a requested task could not be performed (that an ‘‘exceptional circum- stance’’ has been detected). The assumption is that the two parts of the program are written inde- pendently and read more..

  • Page - 366

    Section 13.1.6 Hierarchical Error Handling 351 void callC() // Call a C function from C++; convert err no to a throw { errno = 0; c_function(); if (errno) { // ... local cleanup, if possible and necessary ... throw C_blewit(errno); } } extern "C" void call_from_C() noexcept // Call a C++ function from C; convert a throw to err no { try { c_plus_plus_function(); } catch read more..

  • Page - 367

    352 Exception Handling Chapter 13 However, g() or h() may throw an exception, so f() must contain code ensuring that buf is destroyed correctly in case of an exception. Had g() not thrown an exception, it would have had to report its error some other way. Conse- quently, the comparable code using ordinary code to handle errors instead of exceptions isn’t the plain code read more..

  • Page - 368

    Section 13.2 Exception Guarantees 353 13.2 Exception Guarantees To recover from an error – that is, to catch an exception and continue executing a program – we need to know what can be assumed about the state of the program before and after the attempted recovery action. Only then can recovery be meaningful. Therefore, we call an operation exception- safe if that operation read more..

  • Page - 369

    354 Exception Handling Chapter 13 Both the basic guarantee and the strong guarantee are provided on the condition that • user-supplied operations (such as assignments and swap() functions) do not leave container elements in invalid states, • user-supplied operations do not leak resources, and • destructors do not throw exceptions (§iso.17.6.5.12). Violating a standard-library requirement, read more..

  • Page - 370

    Section 13.3 Resource Management 355 void use_ le(const char ∗ fn) // naive code { FILE ∗ f = fopen(fn,"r"); // ... use f ... fclose(f); } This looks plausible until you realize that if something goes wrong after the call of fopen() and before the call of fclose() , an exception may cause use_ le() to be exited without fclose() being called. Exactly the same problem read more..

  • Page - 371

    356 Exception Handling Chapter 13 strongly resembles the behavior of local objects created by constructors and destroyed by destruc- tors. Thus, we can handle such resource acquisition and release problems using objects of classes with constructors and destructors. For example, we can define a class File_ptr that acts like a FILE ∗: class File_ptr { FILE ∗ p; public: File_ptr(const read more..

  • Page - 372

    Section 13.3 Resource Management 357 It is often suggested that writing a ‘‘handle class’’ (a RAII class) is tedious so that providing a nicer syntax for the catch(...) action would provide a better solution. The problem with that approach is that you need to remember to ‘‘catch and correct’’ the problem wherever a resource is acquired in an undisciplined way (typically read more..

  • Page - 373

    358 Exception Handling Chapter 13 13.3.1 Finally The discipline required to represent a resource as an object of a class with a destructor have both- ered some. Again and again, people have inv ented ‘‘finally’’ language constructs for writing arbi- trary code to clean up after an exception. Such techniques are generally inferior to RAII because they are ad hoc, but read more..

  • Page - 374

    Section 13.3.1 Finally 359 This produced: var = 0 var = 1 nally! var = 7 Goodby, Cruel world! In addition, the memory allocated and pointed to by p and buf is appropriately delete d and free() d. It is generally a good idea to place a guard close to the definition of whatever it is guarding. That way, we can at a glance see what is considered a resource (even if read more..

  • Page - 375

    360 Exception Handling Chapter 13 termination of a program is considered acceptable. For example, it is not unreasonable to consider program termination acceptable if it is easy to rerun the program with inputs and parameters that make repeated failure unlikely. Some distributed systems are like this (as long as the program that terminates is only a part of the complete system), read more..

  • Page - 376

    Section 13.4 Enforcing Invariants 361 However, using such ‘‘ordinary code’’ tends to obscure what is being tested. Are we: • Evaluating the conditions under which we test? (Yes, the 2<debug_level part.) • Evaluating a condition that is expected to be true for some calls and not for others? (No, because we are throwing an exception – unless someone is trying to use read more..

  • Page - 377

    362 Exception Handling Chapter 13 template<bool condition =le vel(default_level), class Except = Error> void dynamic(bool assertion, const string& message ="Asser t::dynamic failed") { if (assertion) return; if (current_mode == Assert_mode::throw_) throw Except{message}; if (current_mode == Assert_mode::terminate_) std::terminate(); } template<> void dynamic<false ,Error>(bool, const string&) // read more..

  • Page - 378

    Section 13.4 Enforcing Invariants 363 void f(int n) // n should be in [1:max) { Assert::dynamic((n<=0 || max<n),Assert::compose(__FILE__,__LINE__,"rang e problem"); // ... } I do not recommend obsessing about the amount of text needed to express an assertion, but by using a namespace directive (§14.2.3) and the default message, we can get to a minimum: void f(int n) // n should be in read more..

  • Page - 379

    364 Exception Handling Chapter 13 void f(int n) { switch (n) { case 0: throw My_error{}; // OK case 1: throw No_copy{}; // error : can’t copy a No_copy case 2: throw My_error; // error : My_error is a type, rather than an object } } The exception object caught (§13.5.2) is in principle a copy of the one thrown (though an optimizer is allowed to minimize copying); that is, read more..

  • Page - 380

    Section 13.5.1 Throwing Exceptions 365 Because an exception is potentially copied several times before it is caught, we don’t usually put huge amounts of data in it. Exceptions containing a few words are very common. The seman- tics of exception propagation are those of initialization, so objects of types with move semantics (e.g., string s) are not expensive to throw. Some read more..

  • Page - 381

    366 Exception Handling Chapter 13 Now no exception will come out of compute() . Declaring a function noexcept can be most valuable for a programmer reasoning about a pro- gram and for a compiler optimizing a program. The programmer need not worry about providing try -clauses (for dealing with failures in a noexcept function) and an optimizer need not worry about control paths read more..

  • Page - 382

    Section 13.5.1.2 The noexcept Operator 367 The double mention of noexcept looks a bit odd, but noexcept is not a common operator. The operand of noexcept() is not evaluated, so in the example we do not get a run-time error if we pass call_f() with an empty vector . A noexcept(expr) operator does not go to heroic lengths to determine whether expr can throw; it simply looks at read more..

  • Page - 383

    368 Exception Handling Chapter 13 add it to a function parameter. This doesn’t change the set of exceptions we can catch; it only restricts us from modifying the exception caught. In principle, an exception is copied when it is thrown (§13.5). The implementation may apply a wide variety of strategies for storing and transmitting exceptions. It is guaranteed, however, that read more..

  • Page - 384

    Section 13.5.2.1 Rethrow 369 void h() { try { // ... code that might throw an exception ... } catch (std::exception& err) { if (can_handle_it_completely) { // ... handle it ... return; } else { // ... do what can be done here ... throw; // rethrow the exception } } } A rethrow is indicated by a throw without an operand. A rethrow may occur in a catch -clause or in a read more..

  • Page - 385

    370 Exception Handling Chapter 13 give them acceptable values. As for functions, the ellipsis, ... , indicates ‘‘any argument’’ (§12.2.4), so catch(...) means ‘‘catch an y exception.’’ For example: void m() { try { // ... something ... } catch (...) { // handle every exception // ... cleanup ... throw; } } 13.5.2.3 Multiple Handlers A try -block may have multiple catch read more..

  • Page - 386

    Section 13.5.2.3 Multiple Handlers 371 catch (std::bad_cast) { // ... handle dynamic_cast failure (§22.2.1) ... } } Here, the exception is never considered. Even if we removed the ‘‘catch-all’’ handler, bad_cast wouldn’t be considered because it is derived from exception . Matching exception types to catch - clauses is a (fast) run-time operation and is not as general as read more..

  • Page - 387

    372 Exception Handling Chapter 13 So, we can catch exceptions thrown by member constructors. Similarly, we can catch exceptions thrown by member destructors in a destructor (though a destructor should never throw). However, we cannot ‘‘repair’’ the object and return normally as if the exception had not happened: an excep- tion from a member constructor means that the member read more..

  • Page - 388

    Section 13.5.2.5 Termination 373 using terminate_handler = void( ∗)(); // from <exception> [[noreturn]] void my_handler() // a ter minate handler cannot return { // handle termination my way } void dangerous() // very! { terminate_handler old = set_terminate(my_handler); // ... set_terminate(old); // restore the old terminate handler } The return value is the previous function given to read more..

  • Page - 389

    374 Exception Handling Chapter 13 catch (const std::bad_alloc&) { cerr << "new ran out of memory\n"; } catch (...) { // ... } This will catch every exception, except those thrown by construction and destruction of namespace and thread-local variables (§13.5.3). There is no way of catching exceptions thrown during initial- ization or destruction of namespace and thread-local read more..

  • Page - 390

    Section 13.6 A vector Implementation 375 The basic tools available for writing exception-safe code are: • The tr y -block (§13.5). • The support for the ‘‘Resource Acquisition Is Initialization’’ technique (§13.3). The general principles to follow are to • Nev er let go of a piece of information before its replacement is ready for use. • Always leave objects in valid read more..

  • Page - 391

    376 Exception Handling Chapter 13 public: using size_type = unsigned int; // type used for vector sizes explicit vector(size_type n, const T& va l = T(), const A& = A()); vector(const vector& a); // copy constr uctor vector& operator=(const vector& a); // copy assignment vector(vector&& a); // move constr uctor vector& operator=(vector&& a); // move assignment ˜vector(); read more..

  • Page - 392

    Section 13.6.1 A Simple vector 377 To handle this problem, we could keep track of which elements have been constructed and destroy those (and only those) in case of an error: template<class T , class A> vector<T,A>::vector(siz e_type n, const T& va l, const A& a) // elaborate implementation :alloc{a} // copy the allocator { elem = alloc.allocate(n); // get memory for read more..

  • Page - 393

    378 Exception Handling Chapter 13 global ::new , the explicit cast to void ∗ ensures that the standard-library placement function (§17.2.4) is used to invoke the constructor, and not some user-defined operator new() for T ∗s. The calls to alloc.construct() in the vector constructors are simply syntactic sugar for this placement new . Simi- larly, the alloc.destroy() call simply read more..

  • Page - 394

    Section 13.6.2 Representing Memory Explicitly 379 ‘‘Resource Acquisition Is Initialization’’ technique (§13.3) can be used to reduce the amount of code that must be written and to make the code more stylized. In this case, the key resource required by the vector is memory to hold its elements. By providing an auxiliary class to represent the notion of memory used by a vector , we can read more..

  • Page - 395

    380 Exception Handling Chapter 13 This definition of the move assignment uses swap() to transfer ownership of any memory allocated for elements. There are no objects of type T to destroy: vector_base deals with memory and leaves concerns about objects of type T to vector . Given vector_base , vector can be defined like this: template<class T , class A = allocator<T> > class read more..

  • Page - 396

    Section 13.6.2 Representing Memory Explicitly 381 Now the constructor can be simply defined: template<class T , class A> vector<T,A>::vector(siz e_type n, const T& va l, const A& a) :vb{a,n} // allocate space for n elements { uninitialized_ ll(vb.elem,vb.elem+n,val); // make n copies of val } The simplification achieved for this constructor carries over to every vector operation read more..

  • Page - 397

    382 Exception Handling Chapter 13 template<class T , class A> vector<T,A>& vector<T ,A>::operator=(const vector& a) // offers the strong guarantee (§13.2) { vector_base<T,A> b(alloc,a.size()); // get memory uninitialized_copy(a.begin(),a.end(),b.elem); // copy elements destroy_elements(); // destroy old elements swap(vb,b); // transfer ownership return ∗this; // implicitly destroy the old read more..

  • Page - 398

    Section 13.6.3 Assignment 383 if (this == &a) return ∗this; // optimize self assignment size_type sz = size(); size_type asz = a.size(); vb.alloc = a.vb.alloc; // copy the allocator if (asz<=sz) { copy(a.begin(),a.begin()+asz,vb.elem); for (T ∗ p = vb.elem+asz; p!=vb.space; ++p) // destroy sur plus elements (§16.2.6) p >˜T(); } else { copy(a.begin(),a.begin()+sz,vb.elem); read more..

  • Page - 399

    384 Exception Handling Chapter 13 13.6.4 Changing Size One of the most useful aspects of vector is that we can change its size to suit our needs. The most popular functions for changing size are v.push_back(x) , which adds an x at the end of v , and v.resiz e(s) , which makes s the number of elements in v . 13.6.4.1 reserve() The key to a simple implementation of such read more..

  • Page - 400

    Section 13.6.4.1 reserve() 385 Whenever reserve() may have moved the elements, any iterators into the vector may have been invalidated (§31.3.3). Remember that a move operation should not throw. In the rare cases where the obvious imple- mentation of a move might throw, we typically go out of our way to avoid that. A throw from a move operation is rare, unexpected, and read more..

  • Page - 401

    386 Exception Handling Chapter 13 the value of the vector remains unchanged, with space left unincremented. However, reserve() may already have reallocated the existing elements. This definition of push_back() contains two ‘‘magic numbers’’ (2 and 8 ). An industrial-strength implementation would not do that, but it would still have values determining the size of the initial read more..

  • Page - 402

    Section 13.7 Advice 387 [5] If you for some reason cannot use exceptions, mimic them; §13.1.5. [6] Use hierarchical error handling; §13.1.6. [7] Keep the individual parts of error handling simple; §13.1.6. [8] Don’t try to catch every exception in every function; §13.1.6. [9] Always provide the basic guarantee; §13.2, §13.6. [10] Provide the strong guarantee unless there is a read more..

  • Page - 403

    This page intentionally left blank read more..

  • Page - 404

    14 Namespaces The year is 787! A.D.? – Monty Python • Composition Problems • Namespaces Explicit Qualification; using -Declarations; using -Directives; Argument-Dependent Lookup; Namespaces Are Open • Modularization and Interfaces Namespaces as Modules; Implementations; Interfaces and Implementations • Composition Using Namespaces Convenience vs. Safety; Namespace Aliases; Namespace Composition; Composition read more..

  • Page - 405

    390 Namespaces Chapter 14 large than with the elegant expression of individual types, algorithms, and data structures. Consider some of the problems that can arise when people fail to design for modularity. For example, a graphics library may provide different kinds of graphical Shape s and functions to help use them: // Graph_lib: class Shape { /* ... */ }; class Line : public read more..

  • Page - 406

    Section 14.2 Namespaces 391 14.2 Namespaces The notion of a namespace is provided to directly represent the notion of a set of facilities that directly belong together, for example, the code of a library. The members of a namespace are in the same scope and can refer to each other without special notation, whereas access from outside the namespace requires explicit notation. In read more..

  • Page - 407

    392 Namespaces Chapter 14 class Line { /* ... */ }; // sequence of Words class Text { /* ... */ }; // sequence of Lines File ∗ open(const char ∗); // open text file Word operator+(const Line&, const Line&); // concatenate } Glyph glyph(Line& ln, int i); // ln[i] Here, the Word and Line in the declaration of Te xt_lib::operator+() refer to Te xt_lib::Word and Te read more..

  • Page - 408

    Section 14.2.1 Explicit Qualification 393 void Parser::logical(bool); // error : no logical() in Parser double Parser::trem(bool); // error : no trem() in Parser (misspelling) double Parser::prim(int); // error : Parser ::prim() takes a bool argument (wrong type) A namespace is a scope. The usual scope rules hold for namespaces. Thus, ‘‘namespace’’ is a very fundamental and read more..

  • Page - 409

    394 Namespaces Chapter 14 for (string buf; iss>>buf;) res.push_back(buf); return res; } A using -declaration introduces a synonym into a scope. It is usually a good idea to keep local syn- onyms as local as possible to avoid confusion. When used for an overloaded name, a using -declaration applies to all the overloaded versions. For example: namespace N { void f(int); void read more..

  • Page - 410

    Section 14.2.3 using -Directives 395 Within a function, a using -directive can be safely used as a notational convenience, but care should be taken with global using -directives because overuse can lead to exactly the name clashes that namespaces were introduced to avoid. For example: namespace Graph_lib { class Shape { /* ... */ }; class Line : Shape { /* ... */ }; class read more..

  • Page - 411

    396 Namespaces Chapter 14 namespace Chrono { class Date { /* ... */ }; bool operator==(const Date&, const std::string&); std::string format(const Date&); // make str ing representation // ... } void f(Chrono::Date d, int i) { std::string s = format(d); // Chrono::for mat() std::string t = format(i); // error : no for mat() in scope } This lookup rule (called argument-dependent read more..

  • Page - 412

    Section 14.2.4 Argument-Dependent Lookup 397 struct Base { void f(N::S); }; struct D : Base { void mf(); void g(N::S x) { f(x); // call Base::f() mf(x); // call D::mf() h(1); // error : no h(int) available } }; In the standard, the rules for argument-dependent lookup are phrased in terms of associated name- spaces (§iso.3.4.2). Basically: • If an argument is a class member, the read more..

  • Page - 413

    398 Namespaces Chapter 14 14.2.5 Namespaces Are Open A namespace is open; that is, you can add names to it from several separate namespace declara- tions. For example: namespace A { int f(); // now A has member f() } namespace A { int g(); // now A has two members, f() and g() } That way, the members of a namespace need not be placed contiguously in a single file. read more..

  • Page - 414

    Section 14.3 Modularization and Interfaces 399 14.3 Modularization and Interfaces Any realistic program consists of a number of separate parts. For example, even the simple ‘‘Hello, world!’’ program involves at least two parts: the user code requests Hello, world! to be printed, and the I/O system does the printing. Consider the desk calculator example from §10.2. It can be read more..

  • Page - 415

    400 Namespaces Chapter 14 The following subsections show how the logical structure of the desk calculator program can be made clear, and §15.3 shows how the program source text can be physically organized to take advantage of it. The calculator is a tiny program, so in ‘‘real life’’ I wouldn’t bother using name- spaces and separate compilation (§2.4.1, §15.1) to the extent read more..

  • Page - 416

    Section 14.3.1 Namespaces as Modules 401 namespace Table { map<string,double> tabl e; } The driver cannot be completely put into a namespace because the language rules require main() to be a global function: namespace Driver { void calculate() { /* ... */ } } int main() { /* ... */ } The error handler is also trivial: namespace Error { int no_of_errors; double error(const string& read more..

  • Page - 417

    402 Namespaces Chapter 14 14.3.2 Implementations What will the code look like once it has been modularized? That depends on how we decide to access code in other namespaces. We can always access names from ‘‘our own’ ’ namespace exactly as we did before we introduced namespaces. However, for names in other namespaces, we have to choose among explicit qualification, using read more..

  • Page - 418

    Section 14.3.2 Implementations 403 double prim(bool get) // handle primar ies { if (get) ts.get(); switch (ts.current().kind) { case Kind::number: // floating-point constant { double v = ts.current().number_value; ts.get(); return v; } case Kind::name: { double& v = table[ts.current().string_value]; if (ts.get().kind == Kind::assign) v = expr(true); // ’=’ seen: assignment return v; } case Kind::minus: read more..

  • Page - 419

    404 Namespaces Chapter 14 [3] If a qualification for a name is uncommon, use explicit qualification to make it clear from where the name comes. [4] Don’t use explicit qualification for names in the same namespace as the user. 14.3.3 Interfaces and Implementations It should be clear that the namespace definition we used for Parser is not the ideal interface for Parser to read more..

  • Page - 420

    Section 14.3.3 Interfaces and Implementations 405 namespace Parser { // user interface double expr(bool); } namespace Parser_impl { // implementer interface using namespace Parser; double prim(bool); double term(bool); double expr(bool); using namespace Lexer; // use all facilities offered by Lexer using Error::error; using Table::table; } or graphically: Parser (user interface) Parser_impl (implementer read more..

  • Page - 421

    406 Namespaces Chapter 14 int k; void f1() { int i = 0; using namespace X; // make names from X accessible i++; // local i j++; // X::j k++; // error : X’s k or the global k? ::k++; // the global k X::k++; // X’s k } void f2() { int i = 0; using X::i; // error : i declared twice in f2() using X::j; using X::k; // hides global k i++; j++; // X::j k++; // read more..

  • Page - 422

    Section 14.4.2 Namespace Aliases 407 namespace American_Telephone_and_Telegraph { // too long // ... } American_Telephone_and_Telegraph::String s3 = "Grieg"; American_Telephone_and_Telegraph::String s4 = "Nielsen"; This dilemma can be resolved by providing a short alias for a longer namespace name: // use namespace alias to shorten names: namespace ATT = American_Telephone_and_Telegraph; read more..

  • Page - 423

    408 Namespaces Chapter 14 namespace My_lib { using namespace His_string; using namespace Her_vector; void my_fct(String&); } Given this, we can now write the program in terms of My_lib : void f() { My_lib::String s = "Byron"; // finds My_lib::His_string::Str ing // ... } using namespace My_lib; void g(Vector<String>& vs) { // ... my_fct(vs[5]); // ... } If an explicitly read more..

  • Page - 424

    Section 14.4.4 Composition and Selection 409 14.4.4 Composition and Selection Combining composition (by using -directives) with selection (by using -declarations) yields the flexi- bility needed for most real-world examples. With these mechanisms, we can provide access to a variety of facilities in such a way that we resolve name clashes and ambiguities arising from their composition. For read more..

  • Page - 425

    410 Namespaces Chapter 14 using Her_string = Her_lib::String; // rename template<class T> using His_vec = His_lib::Vector<T>; // rename template<class T> class List { /* ... */ }; // additional stuff // ... } There is no general language mechanism for renaming, but for types and templates, we can intro- duce aliases with using (§3.4.5, §6.5). 14.4.5 Namespaces and Overloading read more..

  • Page - 426

    Section 14.4.5 Namespaces and Overloading 411 // new user.c: #include "A.h" #include "B.h" using namespace A; using namespace B; void g() { f('a'); // calls the f() from B.h } Had we wanted to keep user.c completely unchanged, we would have placed the using -directives in the header files. However, it is usually best to avoid using -directives in header files, read more..

  • Page - 427

    412 Namespaces Chapter 14 void f() { std::vector<int> v {7, 3, 9, 4, 0, 1}; sort(v); print(v); sort(v,[](int x, int y) { return x>y; }); print(v); sort(v.begin(),v.end()); print(v); sort(v.begin(),v.end(),[](int x, int y) { return x>y; }); print(v); } The namespace lookup rules and the overloading rules for templates ensure that we find and invoke the correct variants of sort() and get read more..

  • Page - 428

    Section 14.4.6 Versioning 413 namespace V3_0 { // ... } namespace V2_4_2 { double f(double); template<class T> class C { /* ... */ }; } } Here, Popular contains three subnamespaces, each defining a version. The inline specifies that V3_2 is the default meaning of Popular . So we can write: using namespace Popular; void f() { f(1); // Popular ::V3_2::f(int) V3_0::f(1); // Popular read more..

  • Page - 429

    414 Namespaces Chapter 14 // file Popular.h: namespace Popular { inline #include "V3_2.h" #include "V3_0.h" #include "V2_4_2.h" } I do not recommend such intricate use of header files unless it is really necessary. The example above repeatedly violates the rules against including into a nonlocal scope and against having a syntactic construct span file boundaries read more..

  • Page - 430

    Section 14.4.7 Nested Namespaces 415 void X::g() { f(); // error : no f() in X Y::f(); // OK } void h() { f(); // error : no global f() Y::f(); // error : no global Y X::f(); // error : no f() in X X::Y::f(); // OK } For examples of nested namespaces in the standard library, see chrono (§35.2) and rel_ops (§35.5.3). 14.4.8 Unnamed Namespaces It is sometimes useful to wrap read more..

  • Page - 431

    416 Namespaces Chapter 14 where $$$ is some name unique to the scope in which the namespace is defined. In particular, unnamed namespaces in different translation units are different. As desired, there is no way of naming a member of an unnamed namespace from another translation unit. 14.4.9 C Headers Consider the canonical first C program: #include <stdio.h> int main() { read more..

  • Page - 432

    Section 14.4.9 C Headers 417 Another advantage is that the using -declaration for printf() prevents a user from (accidentally or deliberately) defining a nonstandard printf() in the global scope. I consider nonlocal using -direc- tives primarily a transition tool. I also use them for essential foundation libraries, such as the ISO C++ standard library (std). Most code referring to names read more..

  • Page - 433

    This page intentionally left blank read more..

  • Page - 434

    15 Source Files and Programs Form must follow function. – Le Corbusier • Separate Compilation • Linkage File-Local Names; Header Files; The One-Definition Rule; Standard-Library Headers; Link- age to Non-C++ Code; Linkage and Pointers to Functions • Using Header Files Single-Header Organization; Multiple-Header Organization; Include Guards • Programs Initialization of Nonlocal Variables; read more..

  • Page - 435

    420 Source Files and Programs Chapter 15 user’s program. For realistically sized applications, even having all of the user’s own code in a sin- gle file is both impractical and inconvenient. The way a program is organized into files can help emphasize its logical structure, help a human reader understand the program, and help the compiler enforce that logical structure. read more..

  • Page - 436

    Section 15.2 Linkage 421 // file2.cpp: extern int x; int f(); void g() { x = f(); } The x and f() used by g() in le2.cpp are the ones defined in le1.cpp . The keyword extern indicates that the declaration of x in le2.cpp is (just) a declaration and not a definition (§6.3). Had x been initialized, extern would simply be ignored because a declaration with an initializer is read more..

  • Page - 437

    422 Source Files and Programs Chapter 15 int x1 = 1; // exter nal linkage: accessible from other translation units extern const char x2 = 'a'; // exter nal linkage: accessible from other translation units Names that a linker does not see, such as the names of local variables, are said to have no linkage. An inline function (§12.1.3, §16.2.8) must be defined identically in read more..

  • Page - 438

    Section 15.2 Linkage 423 To ensure consistency, place aliases, const s, constexpr s, and inline s in header files (§15.2.2). A const can be given external linkage by an explicit declaration: // file1.cpp: extern const int a = 77; // file2.cpp: extern const int a; void g() { cout << a << '\n'; } Here, g() will print 77 . The techniques for managing template definitions read more..

  • Page - 439

    424 Source Files and Programs Chapter 15 15.2.2 Header Files The types in all declarations of the same object, function, class, etc., must be consistent. Conse- quently, the source code submitted to the compiler and later linked together must be consistent. One imperfect but simple method of achieving consistency for declarations in different translation units is to #include header read more..

  • Page - 440

    Section 15.2.2 Header Files 425 Compile-time assertions static_assert(4<=sizeof(int),"small ints"); Include directives #include<algorithm> Macro definitions #de ne VERSION 12.03 Conditional compilation directives #ifdef __cplusplus Comments / ∗ check for end of le ∗/ This rule of thumb for what may be placed in a header is not a language requirement. It is simply a reasonable way read more..

  • Page - 441

    426 Source Files and Programs Chapter 15 Worse, a ‘‘file’’ isn’t a concept that is part of the C++ language definition; there exist implementa- tions that do not store programs in source files. Consequently, the rule in the standard that says that there must be a unique definition of a class, template, etc., is phrased in a somewhat more complicated and subtle read more..

  • Page - 442

    Section 15.2.3 The One-Definition Rule 427 Here are examples of the three ways of violating the ODR: // file1.cpp: struct S1 { int a; char b; }; struct S1 { int a; char b; }; // error : double definition This is an error because a struct may not be defined twice in a single translation unit. // file1.cpp: struct S2 { int a; char b; }; // file2.cpp: struct S2 { read more..

  • Page - 443

    428 Source Files and Programs Chapter 15 15.2.4 Standard-Library Headers The facilities of the standard library are presented through a set of standard headers (§4.1.2, §30.2). No suffix is needed for standard-library headers; they are known to be headers because they are included using the #include<...> syntax rather than #include"..." . The absence of a .h suffix does read more..

  • Page - 444

    Section 15.2.5 Linkage to Non-C++ Code 429 extern "C" char ∗ strcpy(char ∗, const char ∗); The effect of this declaration differs from the effect of the ‘‘plain’’ declaration extern char ∗ strcpy(char ∗, const char ∗); only in the linkage convention used for calling strcpy() . The extern "C" directive is particularly useful because of the close read more..

  • Page - 445

    430 Source Files and Programs Chapter 15 The predefined macro name __cplusplus (§12.6.2) is used to ensure that the C++ constructs are edited out when the file is used as a C header. Any declaration can appear within a linkage block: extern "C" { // any declaration here, for example: int g1; // definition extern int g2; // declaration, not definition } In particular, the scope and read more..

  • Page - 446

    Section 15.2.6 Linkage and Pointers to Functions 431 typedef int ( ∗FT)(const void ∗,const void ∗); // FT has C++ linkage extern "C" { typedef int ( ∗CFT)(const void ∗, const void ∗); // CFT has C linkage void qsort(void ∗ p, size_t n, size_t sz, CFT cmp); // cmp has C linkage } void isort(void ∗ p, size_t n, size_t sz, FT cmp); // cmp has C++ linkage read more..

  • Page - 447

    432 Source Files and Programs Chapter 15 // dc.h: #include <map> #include<string> #include<iostream> namespace Parser { double expr(bool); double term(bool); double prim(bool); } namespace Lexer { enum class Kind : char { name, number, end, plus='+', minus=' ', mul=' ∗', div='/’, print=';', assign='=', lp='(', rp=')' }; struct Token { Kind kind; string string_value; double read more..

  • Page - 448

    Section 15.3.1 Single-Header Organization 433 namespace Table { extern map<string,double> tabl e; } namespace Error { extern int no_of_errors; double error(const string& s); } namespace Driver { void calculate(); } The keyword extern is used for every variable declaration to ensure that multiple definitions do not occur as we #include dc.h in the various .cpp files. The corresponding read more..

  • Page - 449

    434 Source Files and Programs Chapter 15 // ... Lexer::Token Lexer::Token_stream::g et() { /* ... */ } This ensures that the compiler will detect any inconsistencies in the types specified for a name. For example, had get() been declared to return a Token , but defined to return an int , the compilation of lexer.cpp would have failed with a type-mismatch error. If a read more..

  • Page - 450

    Section 15.3.1 Single-Header Organization 435 The physical structure of the system can be presented like this: main.cpp parser.cpp table .cpp lexer.cpp error.cpp dc.h <string> <map> <cctype> <iostream> <sstream> The headers on the top are all headers for standard-library facilities. For many forms of program analysis, these libraries can be ignored because they are well read more..

  • Page - 451

    436 Source Files and Programs Chapter 15 // parser_impl.h: #include "parser.h" #include "error.h" #include "lexer.h" using Error::error; using namespace Lexer; namespace Parser { // interface for implementers double prim(bool get); double term(bool get); double expr(bool get); } The distinction between the user interface and the interface for implementers would be even clearer read more..

  • Page - 452

    Section 15.3.2 Multiple-Header Organization 437 so if we were really keen on minimizing dependencies we could place prim() in its own .cpp file and #include table .h there only: parser.h lexer.h error.h table .h parser_impl.h parser.cpp prim.cpp Such elaboration is not appropriate except for larger modules. For realistically sized modules, it is common to #include extra files where needed for read more..

  • Page - 453

    438 Source Files and Programs Chapter 15 // error.h: #include<string> namespace Error { int Error::number_of_errors; double Error::error(const std::string&); } The implementation is found in error.cpp : // error.cpp: #include "error.h" int Error::number_of_errors; double Error::error(const std::string&) { /* ... */ } The lexer provides a rather large and messy interface: // lexer.h: read more..

  • Page - 454

    Section 15.3.2.1 Other Calculator Modules 439 As usual, we #include the interface offered by the module – in this case, lexer.h – in the mod- ule’s implementation to give the compiler a chance to check consistency. The symbol table is essentially self-contained, although the standard-library header <map> could drag in all kinds of interesting stuff to implement an efficient read more..

  • Page - 455

    440 Source Files and Programs Chapter 15 A word of caution: a few dozen headers plus the standard headers for the program’s execution environment (which can often be counted in the hundreds) are usually manageable. However, if you partition the declarations of a large program into the logically minimal-size headers (putting each structure declaration in its own file, etc.), you read more..

  • Page - 456

    Section 15.3.3 Include Guards 441 The traditional solution is to insert include guards in headers. For example: // error.h: #ifndef CALC_ERROR_H #de ne CALC_ERROR_H namespace Error { // ... } #endif // CALC_ERROR_H The contents of the file between the #ifndef and #endif are ignored by the compiler if CALC_ERROR_H is defined. Thus, the first time error.h is seen during a compilation, read more..

  • Page - 457

    442 Source Files and Programs Chapter 15 15.4.1 Initialization of Nonlocal Variables In principle, a variable defined outside any function (that is, global, namespace, and class static variables) is initialized before main() is invoked. Such nonlocal variables in a translation unit are initialized in their definition order. If such a variable has no explicit initializer, it is by read more..

  • Page - 458

    Section 15.4.2 Initialization and Concurrency 443 15.4.2 Initialization and Concurrency Consider: int x = 3; int y = sqrt(++x); What could be the values of x and y ? The obvious answer is ‘‘3 and 2 !’’ Why? The initialization of a statically allocated object with a constant expression is done at link time, so x becomes 3 .How- ev er, y ’s initializer is not a read more..

  • Page - 459

    444 Source Files and Programs Chapter 15 Like the return value of main() (§2.2.1), exit() ’s argument is returned to ‘‘the system’’ as the value of the program. Zero indicates successful completion. Calling exit() means that the local variables of the calling function and its callers will not have their destructors invoked. Throwing an exception and catching it ensures that read more..

  • Page - 460

    Section 15.5 Advice 445 [8] #include C headers in namespaces to avoid global names; §14.4.9, §15.2.4. [9] Make headers self-contained; §15.2.3. [10] Distinguish between users’ interfaces and implementers’ interfaces; §15.3.2. [11] Distinguish between average users’ interfaces and expert users’ interfaces; §15.3.2. [12] Avoid nonlocal objects that require run-time initialization in code read more..

  • Page - 461

    This page intentionally left blank read more..

  • Page - 462

    Part III Abstraction Mechanisms This part describes C++’s facilities for defining and using new types. Techniques com- monly called object-oriented programming and generic programming are presented. Chapters 16 Classes 17 Construction, Cleanup, Copy, and Move 18 Operator Overloading 19 Special Operators 20 Derived Classes 21 Class Hierarchies 22 Run-Time Type Information 23 Templates 24 Generic read more..

  • Page - 463

    448 Abstraction Mechanisms Part III ‘‘... there is nothing more difficult to carry out, nor more doubtful of success, nor more dangerous to handle, than to initiate a new order of things. For the reformer makes enemies of all those who profit by the old order, and only lukew arm defenders in all those who would profit by the new order...’’ — Niccol `o Machiavelli read more..

  • Page - 464

    16 Classes Those types are not “abstract”; they are as real as int and oat . – Doug McIlroy • Introduction • Class Basics Member Functions; Default Copying; Access Control; class and struct ; Constructors; explicit Constructors; In-Class Initializers; In-Class Function Definitions; Mutability; Self-Refer- ence; Member Access; static Members; Member Types • Concrete Classes Member Functions; read more..

  • Page - 465

    450 Classes Chapter 16 also makes a program more concise. In addition, it makes many sorts of code analysis feasible. In particular, it enables the compiler to detect illegal uses of objects that would otherwise be found only through exhaustive testing. The fundamental idea in defining a new type is to separate the incidental details of the imple- mentation (e.g., the layout read more..

  • Page - 466

    Section 16.2 Class Basics 451 • Members are accessed using . (dot) for objects and > (arrow) for pointers. • Operators, such as + , ! , and [] , can be defined for a class. • A class is a namespace containing its members. • The public members provide the class’s interface and the private members provide imple- mentation details. •A struct is a class where members read more..

  • Page - 467

    452 Classes Chapter 16 struct Date { int d, m, y; void init(int dd, int mm, int yy); // initialize void add_year(int n); // add n years void add_month(int n); // add n months void add_day(int n); // add n days }; Functions declared within a class definition (a struct is a kind of class; §16.2.4) are called member functions and can be invoked only for a specific variable of read more..

  • Page - 468

    Section 16.2.2 Default Copying 453 By default, the copy of a class object is a copy of each member. If that default is not the behavior wanted for a class X , a more appropriate behavior can be provided (§3.3, §17.5). Similarly, class objects can by default be copied by assignment. For example: void f(Date& d) { d = my_bir thday; } Again, the default semantics is read more..

  • Page - 469

    454 Classes Chapter 16 There are several benefits to be obtained from restricting access to a data structure to an explicitly declared list of functions. For example, any error causing a Date to take on an illegal value (for example, December 36, 2016) must be caused by code in a member function. This implies that the first stage of debugging – localization – is read more..

  • Page - 470

    Section 16.2.4 class and struct 455 However, we can also use the access specifier private: to say that the members following are private, just as public: says that the members following are public: struct Date2 { private: int d, m, y; public: Date2(int dd, int mm, int yy); void add_year(int n); // add n years }; Except for the different name, Date1 and Date2 are equivalent. It read more..

  • Page - 471

    456 Classes Chapter 16 class Date { int d, m, y; public: Date(int dd, int mm, int yy); // constructor // ... }; When a class has a constructor, all objects of that class will be initialized by a constructor call. If the constructor requires arguments, these arguments must be supplied: Date today = Date(23,6,1983); Date xmas(25,12,1990); // abbreviated for m Date my_bir thday; // read more..

  • Page - 472

    Section 16.2.5 Constructors 457 reducing the number of related functions is to use default arguments (§12.2.5). For Date , each argu- ment can be given a default value interpreted as ‘‘pick the default: today .’’ class Date { int d, m, y; public: Date(int dd =0, int mm =0, int yy =0); // ... }; Date::Date(int dd, int mm, int yy) { d=dd?dd:today.d; m=mm ?mm:today.m; y=yy read more..

  • Page - 473

    458 Classes Chapter 16 Such implicit conversions can be extremely useful. Complex numbers are an example: if we leave out the imaginary part, we get a complex number on the real axis. That’s exactly what mathematics requires. However, in many cases, such conversions can be a significant source of confusion and errors. Consider Date : void my_fct(Date d); void f() { Date d read more..

  • Page - 474

    Section 16.2.6 explicit Constructors 459 If a constructor is declared explicit and defined outside the class, that explicit cannot be repeated: class Date { int d, m, y; public: explicit Date(int dd); // ... }; Date::Date(int dd) { /* ... */ } // OK explicit Date::Date(int dd) { /* ... */ } // error Most examples where explicit is important involve a single constructor argument. read more..

  • Page - 475

    460 Classes Chapter 16 We can deal with that by introducing default arguments to reduce the number of constructors (§16.2.5). Alternatively, we can add initializers to data members: class Date { int d {today.d}; int m {today.m}; int y {today.y}; public: Date(int, int, int); // day, month, year Date(int, int); // day, month, today’s year Date(int); // day, today’s month and read more..

  • Page - 476

    Section 16.2.8 In-Class Function Definitions 461 class Date { public: void add_month(int n) { m+=n; } // increment the Date’s m // ... private: int d, m, y; }; inline void Date::add_month(int n) // add n months { m+=n; // increment the Date’s m } This latter style is often used to keep class definitions simple and easy to read. It also provides a textual separation of a read more..

  • Page - 477

    462 Classes Chapter 16 The const after the (empty) argument list in the function declarations indicates that these functions do not modify the state of a Date . Naturally, the compiler will catch accidental attempts to violate this promise. For example: int Date::year() const { return ++y; // error : attempt to change member value in const function } When a const member function is read more..

  • Page - 478

    Section 16.2.9.2 Physical and Logical Constness 463 From a user’s point of view, string_rep doesn’t change the state of its Date , so it clearly should be a const member function. On the other hand, the cache and cache_valid members must change occa- sionally for the design to make sense. Such problems could be solved through brute force using a cast, for example, a read more..

  • Page - 479

    464 Classes Chapter 16 struct cache { bool valid; string rep; }; class Date { public: // ... string string_rep() const; // string representation private: cache ∗ c; // initialize in constr uctor void compute_cache_value() const; // fill what cache refers to // ... }; string Date::string_rep() const { if (!c >valid) { compute_cache_value(); c >valid = true; } return c >rep; } The read more..

  • Page - 480

    Section 16.2.10 Self-Reference 465 Date& ad d_year(int n); // add n years Date& ad d_month(int n); // add n months Date& ad d_day(int n); // add n days }; Each (non-static) member function knows for which object it was invoked and can explicitly refer to it. For example: Date& Date::add_year(int n) { if (d==29 && m==2 && !leapyear(y+n)) { // beware of Febr uary 29 read more..

  • Page - 481

    466 Classes Chapter 16 void remove() // remove and destroy this { if (pre) pre >suc = suc; if (suc) suc >pre = pre; delete this; } // ... }; Explicit use of this is required for access to members of base classes from a derived class that is a template (§26.3.7). 16.2.11 Member Access A member of a class X can be accessed by applying the . (dot) operator to an object read more..

  • Page - 482

    Section 16.2.11 Member Access 467 struct S { int m; int f(); static int sm; }; int X::f() { return m; } // X’s f int X::sm {7}; // X’s static member sm (§16.2.12) int (S:: ∗) pmf() {&S::f}; // X’s member f That last construct (a pointer to member) is fairly rare and esoteric; see §20.6. I mention it here just to emphasize the generality of the rule for :: . read more..

  • Page - 483

    468 Classes Chapter 16 Using set_default() , we can change the default date when appropriate. A static member can be referred to like any other member. In addition, a static member can be referred to without mention- ing an object. Instead, its name is qualified by the name of its class. For example: void f() { Date::set_default(4,5,1945); // call Date’s static member read more..

  • Page - 484

    Section 16.2.13 Member Types 469 16.2.13 Member Types Types and type aliases can be members of a class. For example: template<typename T> class Tree { using value_type = T; // member alias enum Policy { rb, splay, treeps }; // member enum class Node { // member class Node ∗ right; Node ∗ left; value_type value; public: void f(Tree ∗); }; Node ∗ top; public: void g(const read more..

  • Page - 485

    470 Classes Chapter 16 16.3 Concrete Classes The previous section discussed bits and pieces of the design of a Date class in the context of intro- ducing the basic language features for defining classes. Here, I reverse the emphasis and discuss the design of a simple and efficient Date class and show how the language features support this design. Small, heavily used read more..

  • Page - 486

    Section 16.3 Concrete Classes 471 // nonmodifying functions for examining the Date: int day() const; Month month() const; int year() const; string string_rep() const; // string representation void char_rep(char s[], in max) const; // C-style string representation // (modifying) functions for changing the Date: Date& ad d_year(int n); // add n years Date& ad d_month(int n); // add n months read more..

  • Page - 487

    472 Classes Chapter 16 is not a common date in my work. Dealing with historical dates before year 1800 or so is a tricky issue best left to expert historians. Furthermore, the day of the month can’t be properly checked in isolation from its month and year. To sav e the user from having to explicitly mention year and month even when they are implied by context, I read more..

  • Page - 488

    Section 16.3 Concrete Classes 473 causes extra work for every user of the structure. Also, even though the Date type seems simple, it takes some thought to get right. For example, incrementing a Date must deal with leap years, with the fact that months are of different lengths, and so on. Also, the day-month-and-year representation is rather poor for many applications. If we read more..

  • Page - 489

    474 Classes Chapter 16 represent that. But I decided that it was better to use an obviously anomalous value to represent ‘‘pick the default month’’ rather than give the appearance that there were 13 months in a year. Note that Month{} , meaning 0 , can be used because it is within the range guaranteed for the enumeration Month (§8.4). I use the member initializer read more..

  • Page - 490

    Section 16.3.1 Member Functions 475 Date& Date::add_month(int n) { if (n==0) return ∗this; if (n>0) { int delta_y = n/12; // number of whole years int mm = static_cast<int>(m)+n%12; // number of months ahead if (12 < mm) { // note: dec is represented by 12 ++delta_y; mm = 12; } // ... handle the cases where the month mm doesn’t have day d ... y += delta_y; m = read more..

  • Page - 491

    476 Classes Chapter 16 Defining such functions in the class itself would complicate the class interface and increase the number of functions that would potentially need to be examined when a change to the representa- tion was considered. How are such functions ‘‘associated’’ with class Date ? In early C++, as in C, their declarations were simply placed in the same file read more..

  • Page - 492

    Section 16.3.2 Helper Functions 477 I’m deliberately being a bit paranoid here. A Month shouldn’t be outside the jan to dec range, but it is possible (someone might have been sloppy with a cast), so I check. The troublesome default_date finally becomes: const Date& Chrono::default_date() { static Date d {1,Month::jan,1970}; return d; } 16.3.3 Overloaded Operators It is often useful read more..

  • Page - 493

    478 Classes Chapter 16 16.3.4 The Significance of Concrete Classes I call simple user-defined types, such as Date , concrete types to distinguish them from abstract classes (§3.2.2) and class hierarchies (§20.4), and also to emphasize their similarity to built-in types such as int and char . Concrete classes are used just like built-in types. Concrete types have also been called value read more..

  • Page - 494

    Section 16.3.4 The Significance of Concrete Classes 479 simple aggregates of built-in types. Alternatively, lack of suitable ‘‘small ef ficient types’’ in an application can lead to gross run-time and space inefficiencies when overly general and expensive classes are used. 16.4 Advice [1] Represent concepts as classes; §16.1. [2] Separate the interface of a class from its read more..

  • Page - 495

    This page intentionally left blank read more..

  • Page - 496

    17 Construction, Cleanup, Copy, and Move Ignorance more frequently begets confidence than does knowledge. – Charles Darwin • Introduction • Constructors and Destructors Constructors and Invariants; Destructors and Resources; Base and Member Destructors; Calling Constructors and Destructors; virtual Destructors • Class Object Initialization Initialization Without Constructors; Initialization Using read more..

  • Page - 497

    482 Construction, Cleanup, Copy, and Move Chapter 17 string ident(string arg) // string passed by value (copied into arg) { return arg; // return str ing (move the value of arg out of ident() to a caller) } int main () { string s1 {"Adams"}; // initialize str ing (constr uct in s1). s1 = indet(s1); // copy s1 into ident() // move the result of ident(s1) into read more..

  • Page - 498

    Section 17.1 Introduction 483 class X { X(Sometype); // ‘‘ordinar y constr uctor’’: create an object X(); // default constructor X(const X&); // copy constr uctor X(X&&); // move constr uctor X& operator=(const X&); // copy assignment: clean up target and copy X& operator=(X&&); // move assignment: clean up target and move ˜X(); // destructor: clean up // ... }; read more..

  • Page - 499

    484 Construction, Cleanup, Copy, and Move Chapter 17 We could try a call: f({2,3,5}); This would print to the logging stream: in_f() v loop 2 ˜v loop 2 v loop 3 ˜v loop 3 v loop 5 ˜v loop 5 ˜in_f() 17.2.1 Constructors and Invariants A member with the same name as its class is called a constructor. For example: class Vector { public: Vector(int s); // ... }; A constructor read more..

  • Page - 500

    Section 17.2.1 Constructors and Invariants 485 Vector::Vector(int s) { if (s<0) thr ow Bad_siz e{s}; sz = s; elem = new double[s]; } This constructor tries to establish the invariant and if it cannot, it throws an exception. If the con- structor cannot establish the invariant, no object is created and the constructor must ensure that no resources are leaked (§5.2, §13.3). A read more..

  • Page - 501

    486 Construction, Cleanup, Copy, and Move Chapter 17 Vector ∗ f(int s) { Vector v1(s); // ... return new Vector(s+s); } void g(int ss) { Vector ∗ p = f(ss); // ... delete p; } Here, the Vector v1 is destroyed upon exit from f() . Also, the Vector created on the free store by f() using new is destroyed by the call of delete . In both cases, Vector ’s destructor is read more..

  • Page - 502

    Section 17.2.3 Base and Member Destructors 487 essential rule, but only through deliberate circumvention involving passing pointers to uninitialized variables as arguments. Doing so violates language rules and the results are usually disastrous. Constructors execute member and base constructors in declaration order (not the order of ini- tializers): if two constructors used a different order, read more..

  • Page - 503

    488 Construction, Cleanup, Copy, and Move Chapter 17 The p >˜X() notation invokes X ’s destructor for ∗p. That notation should never be used for an object that is destroyed in the normal way (by its object going out of scope or being delete d). For a more complete example of explicit management of objects in a memory area, see §13.6.1. If declared for a class X read more..

  • Page - 504

    Section 17.2.5 virtual Destructors 489 void user(Shape ∗ p) { p >draw(); // invoke the appropriate draw() // ... delete p; // invoke the appropriate destructor }; Had Shape ’s destructor not been virtual that delete would have failed to invoke the appropriate derived class destructor (e.g., ˜Circle() ). That failure would cause the resources owned by the deleted object (if read more..

  • Page - 505

    490 Construction, Cleanup, Copy, and Move Chapter 17 Where no constructor requiring arguments is declared, it is also possible to leave out the initial- izer completely. For example: Work alpha; void f() { Work beta; // ... } For this, the rules are not as clean as we might like. For statically allocated objects (§6.4.2), the rules are exactly as if you had used {} , so the read more..

  • Page - 506

    Section 17.3.2 Initialization Using Constructors 491 17.3.2 Initialization Using Constructors Where memberwise copy is not sufficient or desirable, a constructor can be defined to initialize an object. In particular, a constructor is often used to establish an invariant for its class and to acquire resources necessary to do that (§17.2.1). If a constructor is declared for a class, read more..

  • Page - 507

    492 Construction, Cleanup, Copy, and Move Chapter 17 For this reason, {} initialization is sometimes referred to as universal initialization: the notation can be used everywhere. In addition, {} initialization is uniform: wherever you initialize an object of type X with a value v using the {v} notation, the same value of type X (X{v}) is created. The = and () notations for read more..

  • Page - 508

    Section 17.3.2.1 Initialization by Constructors 493 struct S2 { int a,b; S2(int a = 0, int b = 0) : a(aa), b(bb) {} // constructor }; S1 x11(1,2); // error : no constructor S1 x12 {1,2}; // OK: memberwise initialization S1 x13(1); // error : no constructor S1 x14 {1}; // OK: x14.b becomes 0 S2 x21(1,2); // OK: use constructor S2 x22 {1,2}; // OK: use constructor S2 x23(1); // read more..

  • Page - 509

    494 Construction, Cleanup, Copy, and Move Chapter 17 class Vector { public: Vector(); // default constructor : no elements // ... }; A default constructor is used if no arguments are specified or if an empty initializer list is provided: Vector v1; // OK Vector v2 {}; // OK A default argument (§12.2.5) can make a constructor that takes arguments into a default construc- tor. For read more..

  • Page - 510

    Section 17.3.3 Default Constructors 495 The generated int will be initialized to 0 . References and const s must be initialized (§7.7, §7.5). Therefore, a class containing such mem- bers cannot be default constructed unless the programmer supplies in-class member initializers (§17.4.4) or defines a def ault constructor that initializes them (§17.4.1). For example: int glob {9}; struct X { const read more..

  • Page - 511

    496 Construction, Cleanup, Copy, and Move Chapter 17 value. Standard-library containers (e.g., vector and map ) hav e initializer-list constructors, assign- ments, etc. (§31.3.2, §31.4.3). Consider: vector<double> v = { 1, 2, 3.456, 99.99 }; list<pair<string,string>> languages = { {"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"} }; read more..

  • Page - 512

    Section 17.3.4.1 initializer_list Constructor Disambiguation 497 The first rule, ‘‘prefer the default constructor,’’ is basically common sense: pick the simplest con- structor when you can. Furthermore, if you define an initializer-list constructor to do something with an empty list that differs from what the default constructor does, you probably have a design error on your hands. read more..

  • Page - 513

    498 Construction, Cleanup, Copy, and Move Chapter 17 To explicitly use an initializer_list you must #include the header file in which it is defined: <initial- izer_list> . Howev er, since vector , map , etc., use initializer_list s, their headers (<vector>, <map> , etc.) already #include <initializer_list> , so you rarely have to do so directly. The elements read more..

  • Page - 514

    Section 17.3.4.3 Direct and Copy Initialization 499 • The container’s initializer-list constructor can be explicit or not. • The constructor of the element type of the initializer list can be explicit or not. For a vector<vector<double>> , we can see the direct initialization vs. copy initialization distinction applied to elements. For example: vector<vector<double>> vs = { read more..

  • Page - 515

    500 Construction, Cleanup, Copy, and Move Chapter 17 void f(const vector<double>&); void g() { v1 = {9,10,11}; // OK: v1 now has three elements with values {9,10,11} f({9,8,7,6,5,4}); // OK: f is called with the list {9,8,7,6,5,4} } Similarly, the potential ambiguities do not occur for lists of elements of nonintegral types: vector<string> v1 { "Any a"}; // OK: v1 has read more..

  • Page - 516

    Section 17.4.1 Member Initialization 501 The members’ constructors are called before the body of the containing class’s own constructor is executed (§17.2.3). The constructors are called in the order in which the members are declared in the class rather than the order in which the members appear in the initializer list. To avoid con- fusion, it is best to specify the read more..

  • Page - 517

    502 Construction, Cleanup, Copy, and Move Chapter 17 class Person { string name; string address; // ... Person(const Person&); Person(const string& n, const string& a); }; Person::Person(const string& n, const string& a) : name{n} { address = a; } Here name is initialized with a copy of n . On the other hand, address is first initialized to the empty string and then a copy of a read more..

  • Page - 518

    Section 17.4.3 Delegating Constructors 503 class X { int a; validate(int x) { if (0<x && x<=max) a=x; else thr ow Bad_X(x); } public: X(int x) { validate(x); } X() { validate(42); } X(string s) { int x = to<int>(s); validate(x); } // §25.2.5.1 // ... }; Verbosity hinders readability and repetition is error-prone. Both get in the way of maintainability. The alternative is read more..

  • Page - 519

    504 Construction, Cleanup, Copy, and Move Chapter 17 called for an object unless its original constructor completed. If all you need is to set a member to a default value (that doesn’t depend on a constructor argu- ment), a member initializer (§17.4.4) may be simpler. 17.4.4 In-Class Initializers We can specify an initializer for a non-static data member in the class declaration. read more..

  • Page - 520

    Section 17.4.4 In-Class Initializers 505 private: int a, b; HashFunction algorithm {"MD5"}; // cr yptographic hash to be applied to all As string state {"Constructor run"}; // string indicating state in object life cycle }; If a member is initialized by both an in-class initializer and a constructor, only the constructor’s initialization is done (it ‘‘overrides’’ the read more..

  • Page - 521

    506 Construction, Cleanup, Copy, and Move Chapter 17 17.4.5 static Member Initialization A static class member is statically allocated rather than part of each object of the class. Generally, the static member declaration acts as a declaration for a definition outside the class. For example: class Node { // ... static int node_count; // declaration }; int Node::node_count = 0; // read more..

  • Page - 522

    Section 17.5 Copy and Move 507 17.5 Copy and Move When we need to transfer a value from a to b , we usually have two logically distinct options: • Copy is the conventional meaning of x=y ; that is, the effect is that the values of x and y are both equal to y ’s value before the assignment. • Move leaves x with y ’s former value and y with some read more..

  • Page - 523

    508 Construction, Cleanup, Copy, and Move Chapter 17 First we note that the default copy (copy the members) would be disastrously wrong: the Matrix ele- ments would not be copied, the Matrix copy would have a pointer to the same elements as the source, and the Matrix destructor would delete the (shared) elements twice (§3.3.1). However, the programmer can define any suitable read more..

  • Page - 524

    Section 17.5.1.1 Beware of Default Constructors 509 17.5.1.1 Beware of Default Constructors When writing a copy operation, be sure to copy every base and member. Consider: class X { string s; string s2; vector<string> v; X(const X&) // copy constr uctor :s{a.s}, v{a.v} // probably sloppy and probably wrong { } // ... }; Here, I ‘‘forgot’’ to copy s2 , so it gets default read more..

  • Page - 525

    510 Construction, Cleanup, Copy, and Move Chapter 17 A virtual base (§21.3.5) may appear as a base of several classes in a hierarchy. A default copy constructor (§17.6) will correctly copy it. If you define your own copy constructor, the simplest technique is to repeatedly copy the virtual base. Where the base object is small and the virtual base occurs only a few times in a hierarchy, that read more..

  • Page - 526

    Section 17.5.1.3 The Meaning of Copy 511 void f() { S y {x}; // ‘‘copy’’ x ∗y.p = 1; // change y; affects x ∗x.p = 2; // change x; affects y delete y.p; // affects x and y y.p = new int{3}; // OK: change y; does not affect x ∗x.p = 4; // oops: write to deallocated memory } Here I violated the rule of independence. After the ‘‘copy’’ of x into read more..

  • Page - 527

    512 Construction, Cleanup, Copy, and Move Chapter 17 void f() { S2 y {x}; // ‘‘copy’’ x ∗y.p = 1; // change y, affects x ∗x.p = 2; // change x; affects y y.p.reset(new int{3}); // change y; affects x ∗x.p = 4; // change x; affects y } In fact, shallow copy and such entangled objects are among the sources of demands for garbage collection. Entangled objects lead read more..

  • Page - 528

    Section 17.5.1.3 The Meaning of Copy 513 void write_block(Descriptor d) { if (shared) { rep =clone(); // make a copy of *rep shared = false; // no more sharing } // ... now we can safely write to our own copy of rep ... } Like any other technique, copy-on-write is not a panacea, but it can be an effective combination of the simplicity of true copy and the efficiency read more..

  • Page - 529

    514 Construction, Cleanup, Copy, and Move Chapter 17 [1] Prohibit copying of the base class: delete the copy operations (§17.6.4). [2] Prevent conversion of a pointer to a derived to a pointer to a base: make the base class a private or protected base (§20.5). The former would make the initializations of b2 and bb errors; the latter would make the call of naive() and the read more..

  • Page - 530

    Section 17.5.2 Move 515 you drive away in my car, rather than in your freshly made copy of my car. Once I have giv en you an object, you have it and I no longer do. Consequently, we talk about ‘‘giving aw ay,’’ ‘‘handing over,’’ ‘‘transferring ownership of,’ ’ and ‘‘moving’’ physical objects. Many objects in a computer resemble physical objects read more..

  • Page - 531

    516 Construction, Cleanup, Copy, and Move Chapter 17 template<class T> Matrix<T>& Matrix<T>::operator=(Matrix&& a) // move assignment { swap(dim,a.dim); // swap representations swap(elem,a.elem); return ∗this; } Move constructors and move assignments take non-const (rvalue) reference arguments: they can, and usually do, write to their argument. However, the argument of a move read more..

  • Page - 532

    Section 17.5.2 Move 517 Having move operations affects the idiom for returning large objects from functions. Consider: Matrix operator+(const Matrix& a, const Matrix& b) // res[i][j] = a[i][j]+b[i][j] for each i and j { if (a.dim[0]!=b.dim[0] || a.dim[1]!=b.dim[1]) throw std::runtime_error("unequal Matrix siz es in +"); Matrix res{a.dim[0],a.dim[1]}; constexpr auto n = a.size(); for (int i read more..

  • Page - 533

    518 Construction, Cleanup, Copy, and Move Chapter 17 By default, the compiler generates each of these operations if a program uses it. However, if the programmer takes control by defining one or more of those operations, the generation of related operations is suppressed: • If the programmer declares any constructor for a class, the default constructor is not gener- ated for read more..

  • Page - 534

    Section 17.6.1 Explicit Defaults 519 class gslice { valarray<siz e_t> siz e; valarray<siz e_t> stride; valarray<siz e_t> d1; public: // ... gslice(const gslice& a); }; gslice::gslice(const gslice& a) :siz e{a.size }, stride{a.stride}, d1{a.d1} { } This is not only verbose, making it harder to read the definition of gslice , but also opens the oppor- tunity for making mistakes. read more..

  • Page - 535

    520 Construction, Cleanup, Copy, and Move Chapter 17 17.6.3 Using Default Operations This section presents a few examples demonstrating how copy, move, and destructors are logically linked. If they were not linked, errors that are obvious when you think about them would not be caught by the compiler. 17.6.3.1 Default Constructors Consider: struct X { X(int); // require an int to read more..

  • Page - 536

    Section 17.6.3.2 Maintaining Invariants 521 implicit. The result is that a Z can be copied and moved using the default operations: Z v0; // no initialization (oops! possibility of undefined values) Z val {{1,2,3},1,&val[2]}; // OK, but ugly and error-prone Z v2 = val; // copies: v2.largest points into val Z v3 = move(val); // moves: val.elem becomes empty; v3.my_favor ite is read more..

  • Page - 537

    522 Construction, Cleanup, Copy, and Move Chapter 17 void f3() { Handle<int> h1 {ne w int{7}}; Handle<int> h2 {h1}; // error : no copy constr uctor // ... } Had Handle had a default copy constructor, both h1 and h2 would have had a copy of the pointer and both would have delete d it. The results would be undefined and most likely disastrous (§3.3.1). Caveat: the read more..

  • Page - 538

    Section 17.6.3.4 Partially Specified Invariants 523 We defined copy assignment, so we must also define the destructor. That destructor can be =default because all it needs to do is to ensure that the member pos is destroyed, which is what would have been done anyway had the copy assignment not been defined. At this point, we notice that the user-defined copy assignment read more..

  • Page - 539

    524 Construction, Cleanup, Copy, and Move Chapter 17 17.6.4 delete d Functions We can ‘‘delete’’ a function; that is, we can state that a function does not exist so that it is an error to try to use it (implicitly or explicitly). The most obvious use is to eliminate otherwise defaulted functions. For example, it is common to want to prevent the copying of classes read more..

  • Page - 540

    Section 17.6.4 delete d Functions 525 A further use is to control where a class can be allocated: class Not_on_stack { // ... ˜Not_on_stack() = delete; }; class Not_on_free_store { // ... void ∗ operator new(siz e_t) = delete; }; You can’t hav e a local variable that can’t be destroyed (§17.2.2), and you can’t allocate an object on the free store when you have =delete d its read more..

  • Page - 541

    526 Construction, Cleanup, Copy, and Move Chapter 17 [11] Prefer member initialization over assignment in a constructor; §17.4.1.1. [12] Use in-class initializers to provide default values; §17.4.4. [13] If a class is a resource handle, it probably needs copy and move operations; §17.5. [14] When writing a copy constructor, be careful to copy every element that needs to be copied read more..

  • Page - 542

    18 Operator Overloading When I use a word it means just what I choose it to mean – neither more nor less. – Humpty Dumpty • Introduction • Operator Functions Binary and Unary Operators; Predefined Meanings for Operators; Operators and User- Defined Types; Passing Objects; Operators in Namespaces • A Complex Number Type Member and Nonmember Operators; Mixed-Mode Arithmetic; read more..

  • Page - 543

    528 Operator Overloading Chapter 18 represented as user-defined types. For example, if you need complex arithmetic, matrix algebra, logic signals, or character strings in C++, you use classes to represent these notions. Defining oper- ators for such classes sometimes allows a programmer to provide a more conventional and con- venient notation for manipulating objects than could be read more..

  • Page - 544

    Section 18.1 Introduction 529 Many of the most obvious uses of operator overloading are for numeric types. However, the usefulness of user-defined operators is not restricted to numeric types. For example, the design of general and abstract interfaces often leads to the use of operators such as > , [] , and () . 18.2 Operator Functions Functions defining meanings for the read more..

  • Page - 545

    530 Operator Overloading Chapter 18 void f(complex a, complex b) { complex c = a + b; // shor thand complex d = a.operator+(b); // explicit call } Given the previous definition of complex , the two initializers are synonymous. 18.2.1 Binary and Unary Operators A binary operator can be defined by either a non-static member function taking one argument or a nonmember function read more..

  • Page - 546

    Section 18.2.1 Binary and Unary Operators 531 // nonmember functions : X operator (X); // prefix unary minus X operator (X,X); // binar y minus X operator (X&,int); // postfix decrement X operator (); // error : no operand X operator (X,X,X); // error : ter nary X operator%(X); // error : unar y % Operator [] is described in §19.2.1, operator () in §19.2.2, operator > in read more..

  • Page - 547

    532 Operator Overloading Chapter 18 18.2.3 Operators and User-Defined Types An operator function must either be a member or take at least one argument of a user-defined type (functions redefining the new and delete operators need not). This rule ensures that a user cannot change the meaning of an expression unless the expression contains an object of a user-defined type. In read more..

  • Page - 548

    Section 18.2.4 Passing Objects 533 Larger objects, we pass by reference. For example, because a Matrix (a simple matrix of double s; §17.5.1) is most likely larger than a few words, we use pass-by-reference: Matrix operator+(const Matrix&, const Matrix&); // pass-by-const-reference In particular, we use const references to pass large objects that are not meant to be modified by the called read more..

  • Page - 549

    534 Operator Overloading Chapter 18 class ostream { // ... ostream& operator<<(const char ∗); // output C-style string }; extern ostream cout; ostream& operator<<(ostream&, const string&); // output std::string }// namespace std int main() { const char ∗ p = "Hello"; std::string s = "world"; std::cout << p << ", " << s << "!\n"; read more..

  • Page - 550

    Section 18.2.5 Operators in Namespaces 535 operand of a user-defined type. Therefore, user-defined conversions (§18.3.2, §18.4) will be con- sidered. Note that a type alias is just a synonym and not a separate user-defined type (§6.5). Unary operators are resolved analogously. Note that in operator lookup no preference is given to members over nonmembers. This differs from lookup of read more..

  • Page - 551

    536 Operator Overloading Chapter 18 class complex { double re, im; public: complex& operator+=(complex a); // needs access to representation // ... }; complex operator+(complex a, complex b) { return a += b; // access representation through += } The arguments to this operator+() are passed by value, so a+b does not modify its operands. Given these declarations, we can write: void read more..

  • Page - 552

    Section 18.3.2 Mixed-Mode Arithmetic 537 class complex { double re, im; public: complex& operator+=(complex a) { re += a.re; im += a.im; return ∗this; } complex& operator+=(double a) { re += a; return ∗this; } // ... }; The three variants of operator+() can be defined outside complex : complex operator+(complex a, complex b) { return a += b; // calls complex::operator+=(complex) } complex read more..

  • Page - 553

    538 Operator Overloading Chapter 18 18.3.3 Conversions To cope with assignments and initialization of complex variables with scalars, we need a conversion of a scalar (integer or floating-point number) to a complex . For example: complex b {3}; // should mean b.re=3, b.im=0 void comp(complex x) { x=4; // should mean x.re=4, x.im=0 // ... } We can achieve that by providing a read more..

  • Page - 554

    Section 18.3.3 Conversions 539 class complex { double re, im; public: complex(double r =0, double i =0) : re{r}, im{i} { } // ... }; By default, copying complex values is defined as copying the real and imaginary parts (§16.2.2). For example: void f() { complex z; complex x {1,2}; complex y {x}; // y also has the value {1,2} z=x; // z also has the value {1,2} } 18.3.3.1 read more..

  • Page - 555

    540 Operator Overloading Chapter 18 combinatorial explosion of variants that can arise from mixed-mode arithmetic. Where several variants of a function or an operator exist, the compiler must pick ‘‘the right’’ variant based on the argument types and the available (standard and user-defined) conversions. Unless a best match exists, an expression is ambiguous and is an error (see read more..

  • Page - 556

    Section 18.3.4 Literals 541 This would allow us to write: complex z1 {1.2+12e3i}; complex f(double d) { auto x {2.3i}; return x+sqrt(d+12e3i)+12e3i; } This user-defined literal gives us one advantage over what we get from constexpr constructors: we can use user-defined literals in the middle of expressions where the {} notation can only be used when qualified by a type name. The read more..

  • Page - 557

    542 Operator Overloading Chapter 18 For example, given real() and imag() , we can simplify simple, common, and useful operations, such as == , as nonmember functions (without compromising performance): inline bool operator==(complex a, complex b) { return a.real()==b.real() && a.imag ()==b.imag(); } 18.3.6 Helper Functions If we put all the bits and pieces together, the complex class read more..

  • Page - 558

    Section 18.3.6 Helper Functions 543 complex polar(double rho, double theta); complex conj(complex); double abs(complex); double arg(complex); double norm(complex); double real(complex); // for notational convenience double imag(complex); // for notational convenience Finally, we must provide an appropriate set of standard mathematical functions: complex acos(complex); complex asin(complex); complex atan(complex); // read more..

  • Page - 559

    544 Operator Overloading Chapter 18 class Tiny { char v; void assign(int i) { if (i&˜077) thr ow Bad_rang e(); v=i; } public: class Bad_range { }; Tiny(int i) { assign(i); } Tiny& operator=(int i) { assign(i); return ∗this; } operator int() const { return v; } // conversion to int function }; The range is checked whenever a Tiny is initialized by an int and whenever an read more..

  • Page - 560

    Section 18.4.1 Conversion Operators 545 information is lost in the conversion. In general, it is wise to be sparing in the introduction of conversion operators. When used in excess, they lead to ambiguities. Such ambiguities are caught by the compiler, but they can be a nuisance to resolve. Probably the best idea is initially to do conversions by named functions, such as read more..

  • Page - 561

    546 Operator Overloading Chapter 18 18.4.3 Ambiguities An assignment of a value of type V to an object of class X is legal if there is an assignment operator X::operator=(Z) so that V is Z or there is a unique conversion of V to Z . Initialization is treated equiv- alently. In some cases, a value of the desired type can be constructed by repeated use of constructors or read more..

  • Page - 562

    Section 18.4.3 Ambiguities 547 The insistence on strict bottom-up analysis implies that the return type is not used in overload- ing resolution. For example: class Quad { public: Quad(double); // ... }; Quad operator+(Quad,Quad); void f(double a1, double a2) { Quad r1 = a1+a2; // double-precision floating-point add Quad r2 = Quad{a1}+a2; // force quad arithmetic } The reason for this read more..

  • Page - 563

    548 Operator Overloading Chapter 18 [5] Prefer member functions over nonmembers for operations that need access to the representa- tion; §18.3.1. [6] Prefer nonmember functions over members for operations that do not need access to the rep- resentation; §18.3.2. [7] Use namespaces to associate helper functions with ‘‘their’’ class; §18.2.5. [8] Use nonmember functions for symmetric read more..

  • Page - 564

    19 Special Operators We are all special cases. – Albert Camus • Introduction • Special Operators Subscripting; Function Call; Dereferencing; Increment and Decrement; Allocation and De- allocation; User-Defined Literals • A String Class Essential Operations; Access to Characters; Representation; Member Functions; Helper Functions; Using Our String • Friends Finding Friends; Friends and Members read more..

  • Page - 565

    550 Special Operators Chapter 19 19.2.1 Subscripting An operator[] function can be used to give subscripts a meaning for class objects. The second argu- ment (the subscript) of an operator[] function may be of any type. This makes it possible to define vector s, associative arrays, etc. As an example, we can define a simple associative array type like this: struct Assoc { read more..

  • Page - 566

    Section 19.2.2 Function Call 551 struct Action { int operator()(int); pair<int,int> operator()(int,int); double operator()(double); // ... }; void f(Action act) { int x = act(2); auto y = act(3,4); double z = act(2.3); // ... }; An argument list for an operator()() is evaluated and checked according to the usual argument-pass- ing rules. Overloading the function call operator seems to be read more..

  • Page - 567

    552 Special Operators Chapter 19 template<typename Iter, typename Fct> Fct for_each(Iter b, Iter e, Fct f) { while (b != e) f( ∗b++); return f; } At first glance, this technique may look esoteric, but it is simple, efficient, and extremely useful (§3.4.3, §33.4). Note that a lambda expression (§3.4.3, §11.4) is basically a syntax for defining a function object. For example, read more..

  • Page - 568

    Section 19.2.3 Dereferencing 553 Overloading > is primarily useful for creating ‘‘smart pointers,’’ that is, objects that act like point- ers and in addition perform some action whenever an object is accessed through them. The stan- dard-library ‘‘smart pointers’’ unique_ptr and shared_ptr (§5.2.1) provide operator > . As an example, we could define a class Disk_ptr for read more..

  • Page - 569

    554 Special Operators Chapter 19 template<typename T> class Ptr { Y ∗ p; public: Y ∗ operator >() { return p; } // dereference to access member Y& operator ∗() { return ∗p; } // dereference to access whole object Y& operator[](int i) { return p[i]; } // dereference to access element // ... }; If you provide more than one of these operators, it might be wise to read more..

  • Page - 570

    Section 19.2.4 Increment and Decrement 555 void f2(Ptr<X> a) // checked { X v[200]; Ptr<X> p(&v[0],v); p ; ∗p=a; // run-time error: p out of range ++p; ∗p=a; // OK } The increment and decrement operators are unique among C++ operators in that they can be used as both prefix and postfix operators. Consequently, we must define prefix and postfix increment and decrement read more..

  • Page - 571

    556 Special Operators Chapter 19 template<typename T> Ptr Ptr<T>::operator++(int) // increment and return a Ptr with the old value { // ... check that ptr+1 can be pointed to ... Ptr<T> old {ptr,array,sz}; ++ptr; return old; } The pre-increment operator can return a reference to its object. The post-increment operator must make a new object to return. Using Ptr , the read more..

  • Page - 572

    Section 19.2.5 Allocation and Deallocation 557 A more selective, and often better, approach is to supply these operations for a specific class. This class might be the base for many derived classes. For example, we might like to hav e a class Employee provide a specialized allocator and deallocator for itself and all of its derived classes: class Employee { public: // ... void read more..

  • Page - 573

    558 Special Operators Chapter 19 19.2.6 User-defined Literals C++ provides literals for a variety of built-in types (§6.2.6): 123 // int 1.2 // double 1.2F // float 'a' // char 1ULL // unsigned long long 0xD0 // hexadecimal unsigned "as" // C-style string (const char[3]) In addition, we can define literals for user-defined types and new forms of literals for built-in read more..

  • Page - 574

    Section 19.2.6 User-defined Literals 559 suffix and define what is to be done with the literal before it. It is not possible to redefine the mean- ing of a built-in literal suffix or to augment the syntax of literals. There are four kinds of literals that can be suffixed to make a user-defined literal (§iso.2.14.8): • An integer literal (§6.2.4.1): accepted by a literal read more..

  • Page - 575

    560 Special Operators Chapter 19 A template literal operator is a literal operator that takes its argument as a template parameter pack, rather than as a function argument. For example: template<char...> constexpr int operator"" _b3(); // base 3, i.e., ternar y Given that, we get: 201_b3 // means operator"" b3<’2’,’0’,’1’>(); so 9*2+0*3+1 == 19 241_b3 // means read more..

  • Page - 576

    Section 19.2.6 User-defined Literals 561 // ... } using namespace Numerics::literals; The standard library reserves all suffixes not starting with an initial underscore, so define your suf- fixes starting with an underscore or risk your code breaking in the future: 123km // reser ved by the standard librar y 123_km // available for your use 19.3 A String Class The relatively simple read more..

  • Page - 577

    562 Special Operators Chapter 19 String(String&& x); // move constr uctor String& operator=(String&& x); // move assignment ˜String() { if (short_max<sz) delete[] ptr; } // destructor // ... }; This String has value semantics. That is, after an assignment s1=s2 , the two strings s1 and s2 are fully distinct, and subsequent changes to one have no effect on the other. The read more..

  • Page - 578

    Section 19.3.2 Access to Characters 563 int hash(const String& s) { int h {s[0]}; for (int i {1}; i!=s.size(); i++) h ˆ= s[i]>>1; // unchecked access to s return h; } Here, using the checked at() would be redundant because we correctly access s only from 0 to s.size() 1 . We can use at() where we see a possibility of mistakes. For example: void print_in_order(const read more..

  • Page - 579

    564 Special Operators Chapter 19 public: // ... private: static const int short_max = 15; int sz; // number of characters char ∗ ptr; union { int space; // unused allocated space char ch[shor t_max+1]; // leave space for terminating 0 }; void check(int n) const // range check { if (n<0 || sz<=n) throw std::out_of_rang e("String::at()"); } // ancillar y member functions: read more..

  • Page - 580

    Section 19.3.3.1 Ancillary Functions 565 19.3.3.1 Ancillary Functions In addition to functions intended for general use, I found that my code became cleaner when I pro- vided three ancillary functions as ‘‘building blocks’’ to help me with the somewhat tricky represen- tation and to minimize code replication. Tw o of those need to access the representation of String , so I read more..

  • Page - 581

    566 Special Operators Chapter 19 else { // grab the elements ptr = x.ptr; sz = x.sz; space = x.space; x.ptr = x.ch; // x="" x.sz = 0; x.ch[0]=0; } } It too unconditionally makes its target a copy of its argument. However, it does not leave its argu- ment owning any free store. I could also have used memcpy() in the long string case, but since a long string read more..

  • Page - 582

    Section 19.3.4 Member Functions 567 String::String(String&& x) // move constr uctor { move_from(x); } Like the copy constructor, the copy assignment uses copy_from() to clone its argument’s representa- tion. In addition, it has to delete any free store owned by the target and make sure it does not get into trouble with self-assignment (e.g., s=s ): String& String::operator=(const read more..

  • Page - 583

    568 Special Operators Chapter 19 ptr[sz] = c; // add c at end ptr[++sz] = 0; // increase size and set terminator return ∗this; } There is a lot going on here: operator+=() has to keep track of which representation (short or long) is used and whether there is extra space available to expand into. If more space is needed, expand() is called to allocate that space and move read more..

  • Page - 584

    Section 19.3.5 Helper Functions 569 bool operator==(const String& a, const String& b) { if (a.size()!=b.siz e()) return false; for (int i = 0; i!=a.size(); ++i) if (a[i]!=b[i]) return false; return true; } bool operator!=(const String& a, const String& b) { return !(a==b); } Adding < , etc., would be trivial. To support the range-for loop, we need begin() and end() (§9.5.1). Again, we read more..

  • Page - 585

    570 Special Operators Chapter 19 String operator+(const String& a, const String& b) // concatenation { String res {a}; res += b; return res; } I feel that I may have slightly ‘‘cheated’’ here. Should I have provided a member += that added a C- style string to the end? The standard-library string does, but without it, concatenation with a C-style string still works. For read more..

  • Page - 586

    Section 19.3.6 Using Our String 571 String s2 = "Hell"; s2 += " and high water"; cout << s2 << '\n'; String s3 = "qwerty"; s3 = s3; String s4 ="the quick bro wn fox jumped over the lazy dog"; s4 = s4; cout << s3 << " " << s4 << "\n"; cout << s + ". " + s3 + String(". ") + read more..

  • Page - 587

    572 Special Operators Chapter 19 class Matrix { Vector v[rc_max]; // ... friend Vector operator ∗(const Matrix&, const Vector&); }; Now operator ∗() can reach into the implementation of both Vector and Matrix . That would allow sophisticated implementation techniques, but a simple implementation would be: Vector operator ∗(const Matrix& m, const Vector& v) { Vector r; for (int i = read more..

  • Page - 588

    Section 19.4 Friends 573 template<typename T> class X { friend T; friend class T; // redundant ‘‘class’’ // ... }; Often, there is a choice between making a class a member (a nested class) or a nonmember friend (§18.3.1). 19.4.1 Finding Friends A friend must be previously declared in an enclosing scope or defined in the non-class scope imme- diately enclosing the class read more..

  • Page - 589

    574 Special Operators Chapter 19 Thus, a friend function should be explicitly declared in an enclosing scope or take an argument of its class or a class derived from that. If not, the friend cannot be called. For example: // no f() in this scope class X { friend void f(); // useless friend void h(const X&); // can be found through its argument }; void g(const X& read more..

  • Page - 590

    Section 19.4.2 Friends and Members 575 The global function f1() has a similar property because implicit conversions are not used for non- const reference arguments (§7.7). However, conversions may be applied to the arguments of f2() and f3() : void h() { f1(99); // error : f1(X(99)) not tried: non-const X& argument f2(99); // OK: f2(X(99)); const X& argument f3(99); // OK: read more..

  • Page - 591

    576 Special Operators Chapter 19 19.5 Advice [1] Use operator[]() for subscripting and for selection based on a single value; §19.2.1. [2] Use operator()() for call semantics, for subscripting, and for selection based on multiple val- ues; §19.2.2. [3] Use operator >() to dereference ‘‘smart pointers’’; §19.2.3. [4] Prefer prefix ++ over suffix ++ ; §19.2.4. [5] Define the read more..

  • Page - 592

    20 Derived Classes Do not multiply objects without necessity. – William Occam • Introduction • Derived Classes Member Functions; Constructors and Destructors • Class Hierarchies Type Fields; Virtual Functions; Explicit Qualification; Override Control; using Base Mem- bers; Return Type Relaxation • Abstract Classes • Access Control protected Members; Access to Base Classes; using -Declarations read more..

  • Page - 593

    578 Derived Classes Chapter 20 the issue becomes how to represent relationships among concepts. However, we can’t express arbi- trary relationships directly in a programming language. Even if we could, we wouldn’t want to. To be useful, our classes should be more narrowly defined than our everyday concepts – and more pre- cise. The notion of a derived class and its read more..

  • Page - 594

    Section 20.2 Derived Classes 579 struct Employee { string rst_name , family_name; char middle_initial; Date hiring_date; short depar tment; // ... }; Next, we might try to define a manager: struct Manager { Employee emp; // manager’s employee record list<Employee ∗> group; // people managed short level; // ... }; A manager is also an employee; the Employee data is stored in the read more..

  • Page - 595

    580 Derived Classes Chapter 20 A popular and efficient implementation of the notion of derived classes has an object of the derived class represented as an object of the base class, with the information belonging specifically to the derived class added at the end. For example: rst_name family_name ... rst_name family_name ... group level ... Employee : Manager : No memory overhead is read more..

  • Page - 596

    Section 20.2 Derived Classes 581 Using a class as a base is equivalent to defining an (unnamed) object of that class. Conse- quently, a class must be defined in order to be used as a base (§8.2.2): class Employee; // declaration only, no definition class Manager : public Employee { // error : Employee not defined // ... }; 20.2.1 Member Functions Simple data structures, read more..

  • Page - 597

    582 Derived Classes Chapter 20 This comes as a surprise to some, but consider the alternative: that a member function of a derived class could access the private members of its base class. The concept of a private member would be rendered meaningless by allowing a programmer to gain access to the private part of a class simply by deriving a new class from it. read more..

  • Page - 598

    Section 20.2.2 Constructors and Destructors 583 starting with the most fundamental (e.g., base classes) and building what depends on that (e.g., derived classes) later. We build from the roots (base classes) toward the leaves (derived classes). 20.3 Class Hierarchies A derived class can itself be a base class. For example: class Employee { /* ... */ }; class Manager : public Employee read more..

  • Page - 599

    584 Derived Classes Chapter 20 Solution [4] is a special type-safe variation of solution [2]. Combinations of solutions [1] and [4] are particularly interesting and powerful; in almost all situations, they yield cleaner code than do solutions [2] and [3]. Let us first examine the simple type-field solution to see why it is typically best avoided. The manager/employee example could read more..

  • Page - 600

    Section 20.3.1 Type Fields 585 void print_list(const list<Employee ∗>& elist) { for (auto x : elist) print_employee(x); } This works fine, especially in a small program maintained by a single person. However, it has a fundamental weakness in that it depends on the programmer manipulating types in a way that can- not be checked by the compiler. This problem is usually made read more..

  • Page - 601

    586 Derived Classes Chapter 20 class Employee { public: Employee(const string& name , int dept); virtual void print() const; // ... private: string rst_name , family_name; short depar tment; // ... }; The keyword virtual indicates that print() can act as an interface to the print() function defined in this class and print() functions defined in classes derived from it. Where such read more..

  • Page - 602

    Section 20.3.2 Virtual Functions 587 A function from a derived class with the same name and the same set of argument types as a virtual function in a base is said to override the base class version of the virtual function. Furthermore, it is possible to override a virtual function from a base with a more derived return type (§20.3.6). Except where we explicitly say which read more..

  • Page - 603

    588 Derived Classes Chapter 20 a table of pointers to functions. That table is usually called the virtual function table or simply the vtbl . Each class with virtual functions has its own vtbl identifying its virtual functions. This can be represented graphically like this: rst_name second_name ... ... Employee::print() vtbl : Employee : rst_name second_name ... group level ... ... read more..

  • Page - 604

    Section 20.3.3 Explicit Qualification 589 Otherwise, Manager::print() would suffer an infinite recursion. The use of a qualified name has another desirable effect. That is, if a virtual function is also inline (as is not uncommon), then inline substitution can be used for calls specified using :: . This provides the programmer with an efficient way to handle some important special read more..

  • Page - 605

    590 Derived Classes Chapter 20 • override : The function is meant to override a virtual function in a base class (§20.3.4.1). • nal : The function is not meant to be overridden (§20.3.4.2). In the absence of any of these controls, a non-static member function is virtual if and only if it over- rides a virtual function in a base class (§20.3.2). A compiler can warn read more..

  • Page - 606

    Section 20.3.4.1 override 591 a special meaning in a few contexts but can be used as an identifier elsewhere. For example: int override = 7; struct Dx : Base { int override; int f() override { return override + ::override; } }; Don’t indulge in such cleverness; it complicates maintenance. The only reason that override is a contextual keyword, rather than an ordinary keyword, is read more..

  • Page - 607

    592 Derived Classes Chapter 20 In a realistic class hierarchy, there would be several intermediate classes between the general inter- face (here, Node ) and the derived class representing a specific language construct (here, If_state- ment ). However, the key point about this example is that Node::type() is meant to be overridden (that’s why it’s declared virtual ) and its read more..

  • Page - 608

    Section 20.3.4.2 nal 593 void g() nal // OK { // ... } Like override (§20.3.4.1), nal is a contextual keyword. That is, nal has a special meaning in a few contexts but can be used as an ordinary identifier elsewhere. For example: int nal = 7; struct Dx : Base { int nal; int f() nal { return nal + :: nal; } }; Don’t indulge in such cleverness; it complicates maintenance. read more..

  • Page - 609

    594 Derived Classes Chapter 20 void use2(D2 d) { d.f(1); // call D2::f(int), that is, Base::f(int) Base& br = d br.f(1); // call Base::f(int) } This is a simple consequence of a class also being considered a namespace (§16.2). Several using -declarations can bring in names from multiple base classes. For example: struct B1 { void f(int); }; struct B2 { void f(double); }; struct D read more..

  • Page - 610

    Section 20.3.5.1 Inheriting Constructors 595 Unfortunately, we would soon find out that this definition is rather incomplete. For example: Vector<int> v { 1, 2, 3, 5, 8 }; // error : no initializer-list constructor A quick check will show that Vector failed to inherit any constructors from std::vector . That’s not an unreasonable rule: if a class adds data members to a base read more..

  • Page - 611

    596 Derived Classes Chapter 20 struct D1 : B1 { using B1::B1; // implicitly declares D1(int) int x {0}; // note: x is initialized }; void test() { D1 d {6}; // d.x is zero } Most often it is best to avoid being clever and restrict the use of inheriting constructors to the sim- ple cases where no data members are added. 20.3.6 Return Type Relaxation There is a relaxation read more..

  • Page - 612

    Section 20.3.6 Return Type Relaxation 597 This means that given an object of class Expr , a user can create a new object of ‘‘just the same type.’’ For example: void user(Expr ∗ p) { Expr ∗ p2 = p >new_expr(); // ... } The pointer assigned to p2 is declared to point to a ‘‘plain Expr ,’’ but it will point to an object of a type derived from Expr , read more..

  • Page - 613

    598 Derived Classes Chapter 20 sense only as the base of some class derived from it. This can be seen from the fact that it is not possible to provide sensible definitions for its virtual functions: class Shape { public: virtual void rotate(int) { throw runtime_error{"Shape::rotate"}; } // inelegant virtual void draw() const { throw runtime_error{"Shape::draw"}; } // read more..

  • Page - 614

    Section 20.4 Abstract Classes 599 A pure virtual function that is not defined in a derived class remains a pure virtual function, so the derived class is also an abstract class. This allows us to build implementations in stages: class Polygon : public Shape { // abstract class public: bool is_closed() const override { return true; } // ... draw and rotate not overr idden read more..

  • Page - 615

    600 Derived Classes Chapter 20 20.5 Access Control A member of a class can be private , protected ,or public : • Ifitis private , its name can be used only by member functions and friends of the class in which it is declared. • Ifitis protected , its name can be used only by member functions and friends of the class in which it is declared and by member functions read more..

  • Page - 616

    Section 20.5 Access Control 601 Chunk ∗ allocated; Link ∗ free; Link ∗ get_free(); Link ∗ head; }; The definitions of the public functions are pretty strainghtforward: template<class T> void List<T>::insert(T val) { Link ∗ lnk = get_free(); lnk >val = v al; lnk >next = head; head = lnk; } template<class T> T List<T>::g et() { if (head == 0) throw Under ow{}; // read more..

  • Page - 617

    602 Derived Classes Chapter 20 template<class T> auto List<T>::get_free() > Link ∗ { // ... } Nonmember functions (except friends) do not have such access: template<typename T> void would_be_meddler(List<T> ∗ p) { List<T>::Link ∗ q=0; // error : List<T>::Link is priv ate // ... q=p >free; // error : List<T>::free is priv ate // ... if read more..

  • Page - 618

    Section 20.5 Access Control 603 template<class T> class List { private: Link3<T> ∗ free; // ... }; A compiler may reorder sections of a class with separate access specifiers (§8.2.6). For example: class S { public: int m1; public: int m2; }; The compiler may decide for m2 to precede m1 in the layout of an S object. Such reordering could come as a surprise to the read more..

  • Page - 619

    604 Derived Classes Chapter 20 void f(Buffer& b) { b[3] = 'b'; // OK (checked) b.access(3) = 'c'; // error : Buffer ::access() is protected } For another example, see Window_with_border in §21.3.5.2. A derived class can access a base class’s protected members only for objects of its own type: class Buffer { protected: char a[128]; // ... }; class Linked_buffer : public Buffer { read more..

  • Page - 620

    Section 20.5.1.1 Use of protected Members 605 However, none of these objections are significant for protected member functions; protected is a fine way of specifying operations for use in derived classes. The Ival_slider in §21.2.2 is an e xam- ple of this. Had the implementation class been private in this example, further derivation would have been infeasible. On the other hand, read more..

  • Page - 621

    606 Derived Classes Chapter 20 20.5.2.1 Multiple Inheritance and Access Control If the name of a base class can be reached through multiple paths in a multiple-inheritance lattice (§21.3), it is accessible if it is accessible through any path. For example: struct B { int m; static int sm; // ... }; class D1 : public virtual B { /* ... */ } ; class D2 : public virtual B { /* ... read more..

  • Page - 622

    Section 20.5.3 using -Declarations and Access Control 607 When a using -declaration is combined with private or protected derivation, it can be used to specify interfaces to some, but not all, of the facilities usually offered by a class. For example: class BB : private B { // give access to B::b and B::c, but not B::a public: using B::b; using B::c; }; See also §20.3.5. 20.6 read more..

  • Page - 623

    608 Derived Classes Chapter 20 One simple way of doing that is to send a string representing the operation to be invoked. For example, to invoke suspend() we could send the string "suspend" . Howev er, someone has to create that string and someone has to decode it to determine to which operation it corresponds – if any. Often, that seems indirect and tedious. read more..

  • Page - 624

    Section 20.6.1 Pointers to Function Members 609 Because a pointer to a virtual member (s in this example) is a kind of offset, it does not depend on an object’s location in memory. A pointer to a virtual member can therefore be passed between dif- ferent address spaces as long as the same object layout is used in both. Like pointers to ordinary functions, pointers to read more..

  • Page - 625

    610 Derived Classes Chapter 20 void f(C& z1, C& z2) { C ∗ p = &z2; Pm pf = &C::print; Pm pm = &C::val; z1.print(1); (z1. ∗pf)(2); z1. ∗pm = "nv1 "; p > ∗pm = "nv2 "; z2.print(3); (p > ∗pf)(4); pf = &C::f1; // error : retur n type mismatch pf = &C::f2; // error : argument type mismatch pm = &C::i; // error : type mismatch read more..

  • Page - 626

    Section 20.7 Advice 611 20.7 Advice [1] Avoid type fields; §20.3.1. [2] Access polymorphic objects through pointers and references; §20.3.2. [3] Use abstract classes to focus design on the provision of clean interfaces; §20.4. [4] Use override to make overriding explicit in large class hierarchies; §20.3.4.1. [5] Use nal only sparingly; §20.3.4.2. [6] Use abstract classes to specify read more..

  • Page - 627

    This page intentionally left blank read more..

  • Page - 628

    21 Class Hierarchies Abstraction is selective ignorance. – Andrew Koenig • Introduction • Design of Class Hierarchies Implementation Inheritance; Interface Inheritance; Alternative Implementations; Localizing Object Creation • Multiple Inheritance Multiple Interfaces; Multiple Implementation Classes; Ambiguity Resolution; Repeated Use of a Base Class; Virtual Base Classes; Replicated vs. Virtual Bases read more..

  • Page - 629

    614 Class Hierarchies Chapter 21 The idea is to have a class Ival_box (‘‘integer value input box’ ’) that knows what range of input values it will accept. A program can ask an Ival_box for its value and ask it to prompt the user if necessary. In addition, a program can ask an Ival_box if a user changed the value since the program last looked at it: value user (via read more..

  • Page - 630

    Section 21.2.1 Implementation Inheritance 615 The default implementation of the functions is pretty sloppy and is provided here primarily to illus- trate the intended semantics. A realistic class would, for example, provide some range checking. A programmer might use these ‘‘ival classes’’ like this: void interact(Ival_box ∗ pb) { pb >prompt(); // aler t user // ... int i = pb read more..

  • Page - 631

    616 Class Hierarchies Chapter 21 int get_value() override; // get value from user and deposit it in val void prompt() override; }; The data members of Ival_box were declared protected to allow access from derived classes. Thus, Ival_slider::g et_value() can deposit a value in Ival_box::val .A protected member is accessible from a class’s own members and from members of derived classes, read more..

  • Page - 632

    Section 21.2.1.1 Critique 617 Bananas,’’ ‘‘Liberated Software,’’ and ‘‘Compiler Whizzes’’? We would have to maintain four dis- tinct versions of our program: class Ival_box : public BBwidget { /* ... */ }; // BB version class Ival_box : public CWwidget { /* ... */ }; // CW version class Ival_box : public IBwidget { /* ... */ }; // IB version class Ival_box : read more..

  • Page - 633

    618 Class Hierarchies Chapter 21 Several alternative approaches can be taken to achieve this. Here, I present one that maps cleanly into the C++ language. First, I specify class Ival_box as a pure interface: class Ival_box { public: virtual int get_value() = 0; virtual void set_value(int i) = 0; virtual void reset_value(int i) = 0; virtual void prompt() = 0; virtual bool read more..

  • Page - 634

    Section 21.2.2 Interface Inheritance 619 effects. Similarly, making the ‘‘implementation class’’ BBwidget a member of Ival_box is not a solution because a class cannot override virtual functions of its members. Representing the win- dowbya BBwidget ∗ member in Ival_box leads to a completely different design with a separate set of tradeoffs. To some people, the words ‘‘multiple read more..

  • Page - 635

    620 Class Hierarchies Chapter 21 21.2.3 Alternative Implementations This design is cleaner and more easily maintainable than the traditional one – and no less efficient. However, it still fails to solve the version control problem: class Ival_box { /* ... */ }; // common class Ival_slider : public Ival_box, protected BBwidget { /* ... */ }; // for BB class Ival_slider : public read more..

  • Page - 636

    Section 21.2.3 Alternative Implementations 621 Usually, we can do better yet by utilizing more specific classes in the implementation hierarchy. For example, if the ‘‘Big Bucks Inc. ’’ system has a slider class, we can derive our Ival_slider directly from the BBslider : class BB_ival_slider : public Ival_slider, protected BBslider { /* ... */ }; class CW_ival_slider : public read more..

  • Page - 637

    622 Class Hierarchies Chapter 21 Ival_box Ival_slider Ival_dial i ash ipopup CWsl CWsl CWsl CWislider BBislider CWipop CWi BBipop BBi BBslider BBslider BBb&w The original Ival_box class hierarchy appears unchanged surrounded by implementation classes. 21.2.3.1 Critique The abstract class design is flexible and almost as simple to deal with as the equivalent design that relies on a common base read more..

  • Page - 638

    Section 21.2.4 Localizing Object Creation 623 21.2.4 Localizing Object Creation Most of an application can be written using the Ival_box interface. Further, should the derived inter- faces evolve to provide more facilities than plain Ival_box , then most of an application can be writ- ten using the Ival_box , Ival_slider , etc., interfaces. However, the creation of objects must be read more..

  • Page - 639

    624 Class Hierarchies Chapter 21 void user(Ival_maker& im) { unique_ptr<Ival_box> pb {im.dial(0,99)}; // create appropriate dial // ... } BB_maker BB_impl; // for BB users LS_maker LS_impl; // for LS users void driver() { user(BB_impl); // use BB user(LS_impl); // use LS } Passing arguments to such ‘‘virtual constructors’’ is a bit tricky. In particular, we cannot override the base read more..

  • Page - 640

    Section 21.3.2 Multiple Implementation Classes 625 satellites would be rocks, debris from old space vehicles, communication satellites, and the Interna- tional Space Station. These kinds of satellites would be objects of classes derived from Satellite . Such derived classes would add data members and functions and would override some of Satellite ’s virtual functions to adjust their read more..

  • Page - 641

    626 Class Hierarchies Chapter 21 class Satellite { public: virtual Pos center() const = 0; // center of gravity // ... }; class Displayed { public: virtual void draw() = 0; // ... }; class Comm_sat : public Satellite, public Displayed { public: Pos center() const override; // overr ide Satellite::center() void draw() override; // overr ide Displayed::draw() // ... }; This ensures that read more..

  • Page - 642

    Section 21.3.2 Multiple Implementation Classes 627 Why would anyone want a class Comm_sat ? Contrary to some people’s conjectures, the Satel- lite example is real. There really was – and maybe there still is – a program constructed along the lines used to describe multiple implementation inheritance here. It was used to study the design of communication systems involving read more..

  • Page - 643

    628 Class Hierarchies Chapter 21 call to have the same effect independently of which interface was used to find the function (§20.3.2). In the implementation of an overriding function, it is often necessary to explicitly qualify the name to get the right version from a base class. A qualified name, such as Telstar::draw , can refer to a draw declared either in Telstar or read more..

  • Page - 644

    Section 21.3.3 Ambiguity Resolution 629 class Satellite : public SimObj { // map SimObj facilities to something easier to use for Satellite simulation public: virtual Debug_info get_debug(); // call SimObj::DBinf() and extract infor mation // ... }; class Displayed : public Widget { // map Widget facilities to something easier to use to display Satellite simulation results public: virtual read more..

  • Page - 645

    630 Class Hierarchies Chapter 21 separate functions. There is no direct language solution to this (exotic) problem, but adding inter- mediate classes will do: struct WWindow : Window { using Window::Window; // inherit constr uctors virtual void win_draw() = 0; // force derived class to overr ide void draw() override nal { win_draw(); } // display image }; struct CCowboy : Cowboy{ read more..

  • Page - 646

    Section 21.3.4 Repeated Use of a Base Class 631 class Transmitter : public Storable { public: void write() override; // ... }; class Receiver : public Storable { public: void write() override; // ... }; class Radio : public Transmitter, public Receiver { public: string get_ le() override; void read() override; void write() override; // ... }; Given that, we could imagine two cases: [1] A read more..

  • Page - 647

    632 Class Hierarchies Chapter 21 21.3.5 Virtual Base Classes The Radio example in the previous subsection works because class Storable can be safely, con- veniently, and efficiently replicated. The reason for that is simply that Storable is an abstract class providing a pure interface. A Storable object holds no data of its own. This is the simplest case and the one that offers read more..

  • Page - 648

    Section 21.3.5 Virtual Base Classes 633 Storable Receiver Transmitter Radio Compare this diagram with the drawing of the Storable object in §21.3.4 to see the difference between ordinary inheritance and virtual inheritance. In an inheritance graph, every base class of a given name that is specified to be virtual will be represented by a single object of that class. On the other hand, each read more..

  • Page - 649

    634 Class Hierarchies Chapter 21 The ‘‘pointers’’ to the shared object representing the virtual base, Storable , will be offsets, and often one of those can be optimized away by placing Storable in a fixed position relative to either the Receiver or the Transmitter subobject. Expect a storage overhead of one word for each virtual base. 21.3.5.1 Constructing Virtual Bases read more..

  • Page - 650

    Section 21.3.5.1 Constructing Virtual Bases 635 class. The fact that both B and C initialized V is irrelevant because the compiler has no idea which of those two initializers to prefer. Thus, only the initializer provided by the most derived class is used. The constructor for a virtual base is called before the constructors for its derived classes. In practice, this is not quite read more..

  • Page - 651

    636 Class Hierarchies Chapter 21 class Clock : public Window_with_border, public Window_with_menu { // clock stuff protected: void own_draw(); // display the clock face and hands public: void draw() override; }; or graphically: Window Window_with_border Window_with_menu Clock The draw() functions can now be defined using the own_draw() functions, so that a caller of any draw() gets Window::draw() read more..

  • Page - 652

    Section 21.3.6 Replicated vs. Virtual Bases 637 class BB_ival_slider : public Ival_slider, // interface protected BBslider // implementation { // implementation of functions required by Ival_slider and BBslider, using facilities from BBslider }; In this example, the two base classes play logically distinct roles. One base is a public abstract class providing the interface, and the other is a read more..

  • Page - 653

    638 Class Hierarchies Chapter 21 or graphically: Ival_slider Ival_slider Popup_ival_slider BB_ival_slider BB_popup_ival_slider BBslider Surprisingly, there are no fundamental run-time or space advantages to one design over the other. There are logical differences, though. In the replicated Ival_slider design, a BB_popup_ival_slider can’t be implicitly converted to an Ival_slider (because that would be read more..

  • Page - 654

    Section 21.3.6.1 Overriding Virtual Base Functions 639 class Window { // ... virtual void set_color(Color) = 0; // set background color virtual void prompt() = 0; }; class Window_with_border : public virtual Window { // ... void set_color(Color) override; // control background color }; class Window_with_menu : public virtual Window { // ... void prompt() override; // control user interactions read more..

  • Page - 655

    640 Class Hierarchies Chapter 21 21.4 Advice [1] Use unique_ptr or shared_ptr to avoid forgetting to delete objects created using new ; §21.2.1. [2] Avoid date members in base classes intended as interfaces; §21.2.1.1. [3] Use abstract classes to express interfaces; §21.2.2. [4] Give an abstract class a virtual destructor to ensure proper cleanup; §21.2.2. [5] Use override to make read more..

  • Page - 656

    22 Run-Time Type Information Premature optimization is the root of all evil. – Donald Knuth On the other hand, we cannot ignore efficiency. – Jon Bentley • Introduction • Class Hierarchy Navigation dynamic cast ; Multiple Inheritance; static_cast and dynamic_cast ; Recovering an Interface • Double Dispatch and Visitors Double Dispatch; Visitors • Construction and Destruction • Type read more..

  • Page - 657

    642 Run-Time Type Information Chapter 22 22.2 Class Hierarchy Navigation A plausible use of the Ival_box es defined in §21.2 w ould be to hand them to a system that controlled a screen and have that system hand objects back to the application program whenever some activity had occurred. We will refer to the combination of GUI library and operating system facilities that read more..

  • Page - 658

    Section 22.2 Class Hierarchy Navigation 643 The arrows from pw and pb represent the pointers into the object passed, whereas the rest of the arrows represent the inheritance relationships between the different parts of the object passed. The use of type information at run time is conventionally referred to as ‘‘run-time type informa- tion,’’ often abbreviated to RTTI. Casting from read more..

  • Page - 659

    644 Run-Time Type Information Chapter 22 class My_slider: public Ival_slider { // polymor phic base (Ival_slider has virtual functions) // ... }; class My_date : public Date { // base not polymorphic (Date has no virtual functions) // ... }; void g(Ival_box ∗ pb, Date ∗ pd) { My_slider ∗ pd1 = dynamic_cast<My_slider ∗>(pb); // OK My_date ∗ pd2 = dynamic_cast<My_date read more..

  • Page - 660

    Section 22.2.1 dynamic_cast 645 class Io_date : public Date, public Io_obj { }; void f(Io_obj ∗ pio) { Date ∗ pd = dynamic_cast<Date ∗>(pio); // ... } A dynamic_cast to void ∗ can be used to determine the address of the beginning of an object of poly- morphic type. For example: void g(Ival_box ∗ pb, Date ∗ pd) { void ∗ pb2 = dynamic_cast<void ∗>(pb); // OK read more..

  • Page - 661

    646 Run-Time Type Information Chapter 22 void fr(Ival_box& r) { Ival_slider& is = dynamic_cast<Ival_slider&>(r); // r references an Ival_slider! // ... use is ... } The difference in results of a failed dynamic pointer cast and a failed dynamic reference cast reflects a fundamental difference between references and pointers. If a user wants to protect against bad casts to read more..

  • Page - 662

    Section 22.2.2 Multiple Inheritance 647 class Component : public virtual Storable { /* ... */ }; class Receiver : public Component { /* ... */ }; class Transmitter : public Component { /* ... */ }; class Radio : public Receiver, public Transmitter { /* ... */ }; or graphically: Storable Component Component Receiver Transmitter Radio Here, a Radio object has two subobjects of class read more..

  • Page - 663

    648 Run-Time Type Information Chapter 22 derived class; §22.2). The equivalent ambiguity for virtual bases occurs when upcasting (that is, toward a base), but such ambiguities are caught at compile time. 22.2.3 static_cast and dynamic_cast A dynamic_cast can cast from a polymorphic virtual base class to a derived class or a sibling class (§22.2.1). A static_cast (§11.5.2) does not e xamine read more..

  • Page - 664

    Section 22.2.3 static_cast and dynamic_cast 649 static_cast<Receiver ∗>(pcr); // error : can’t cast away const dynamic_cast<Receiver ∗>(pcr); // error : can’t cast away const Receiver ∗ pr = const_cast<Receiver ∗>(pcr); // OK // ... } It is not possible to cast to a private base class using static_cast or reinterpret_cast , and ‘‘casting aw ay const ’’ (o r volatile read more..

  • Page - 665

    650 Run-Time Type Information Chapter 22 The critical function in the object I/O system is get_obj() , which reads data from an istream and cre- ates class objects based on that data. Assume that the data representing an object on an input stream is prefixed by a string identifying the object’s class. The job of get_obj() is to read that string and call a function read more..

  • Page - 666

    Section 22.2.4 Recovering an Interface 651 If the provision of the object I/O scaffolding becomes tedious, a template might help: template<class T> struct Io : T, Io_obj { public: Io(istream&); // initialize from input stream Io ∗ clone() const override { return new Io{ ∗this}; } static Io ∗ new_io(istream& is) { return new Io{is}; } // for io_map }; Given this, we can read more..

  • Page - 667

    652 Run-Time Type Information Chapter 22 template<typename T> T ∗ get_val<T>(Io_obj ∗ p) { if (auto pp = dynamic_cast<Io<T> ∗>(p)) return &pp >val; return nullptr; } The user() function now becomes: void user() { // ... open file assumed to hold shapes, and attach ss as an istream for that file ... unique_ptr<Io_obj> p {g et_obj(ss)}; // read object from read more..

  • Page - 668

    Section 22.3 Double Dispatch and Visitors 653 22.3 Double Dispatch and Visitors Classical object-oriented programming is based on selecting a virtual function based on the dynamic type (the type of the most derived class) of an object given only a pointer or a reference to an interface (a base class). In particular, C++ can do this run-time lookup (also called a dynamic read more..

  • Page - 669

    654 Run-Time Type Information Chapter 22 class Circle : public Shape { public: bool intersect(const Shape&) const override; virtual bool intersect(const Circle&) const override; virtual bool intersect(const Triangle&) const override }; class Triangle : public Shape { public: bool intersect(const Shape&) const override; virtual bool intersect(const Circle&) const override; virtual bool intersect(const read more..

  • Page - 670

    Section 22.3.1 Double Dispatch 655 shapes. That is possible [Pirkelbauer,2009], but not in C++11. The awkwardness of double dispatch does not make the problem it is trying to address less important. It is not unusual to want an action, such as intersect(x,y) , that depends on the types of two (or more) operands. Workarounds abound. For example, finding the intersection of read more..

  • Page - 671

    656 Run-Time Type Information Chapter 22 classes derived from class Visitor . The nodes are a hierarchy of classes with a virtual function accept() that takes Visitor& s. For this example, I use a hierarchy of Node s that describe language constructs, as is common in tools based on abstract syntax trees (ASTs): class Visitor; class Node { public: virtual void accept(Visitor&) = read more..

  • Page - 672

    Section 22.3.2 Visitors 657 We can test by making a vector of pair s of pointers to ensure that run-time type resolution is used: void test(Expr& e, Stmt& s) { vector<pair<Node ∗,Visitor∗>> vn {&e,&do1}, {&s,&do1}, {&e,&do2}, {&s,&do2}}; for (auto p : vn) p. rst >accept( ∗p.second); } We get: do1 to Expr do1 to Stmt do2 to Expr do2 to Stmt As read more..

  • Page - 673

    658 Run-Time Type Information Chapter 22 22.5 Type Identification The dynamic_cast operator serves most needs for information about the type of an object at run time. Importantly, it ensures that code written using it works correctly with classes derived from those explicitly mentioned by the programmer. Thus, dynamic_cast preserves flexibility and exten- sibility in a manner similar to read more..

  • Page - 674

    Section 22.5 Type Identification 659 void f(Non_poly& npr, Poly& pr) { cout << typeid(npr).name() << '\n'; // writes something like "Non_poly" cout << typeid(pr).name() << '\n'; // name of Poly or a class derived from Poly } void g() { D1 d1; D2 d2; f(d2,d1); // writes "Non_poly D1" f( ∗static_cast<Poly∗>(nullptr),∗static_cast<Null_poly∗>(nullptr)); // read more..

  • Page - 675

    660 Run-Time Type Information Chapter 22 #include<typeinfo> void g(Component ∗ p) { cout << typeid( ∗p).name(); } The character representation of a class’s name is implementation-defined. This C-style string resides in memory owned by the system, so the programmer should not attempt to delete[] it. 22.5.1 Extended Type Information A type_info object contains only minimal read more..

  • Page - 676

    Section 22.5.1 Extended Type Information 661 ... type_index<typeid(T)> ... icon representation of type icon_table: Associating typeid s with information without modifying system headers allows several people or tools to associate different information with types independently of each other. This is important because the likelihood that someone can come up with a single set of information that read more..

  • Page - 677

    662 Run-Time Type Information Chapter 22 an example of this. If the user is willing and able to modify the definitions of the library classes, say BBwindow , then the use of RTTI can be avoided; otherwise, it is needed. Even if the user is willing to modify the base classes (e.g., to add a virtual function), such modification may cause its own problems. For example, read more..

  • Page - 678

    Section 22.6 Uses and Misuses of RTTI 663 This style of code is less error-prone (better statically type checked) and less verbose than a pure- Object -based alternative. Combined with the use of virtual functions, this technique handles most cases. In a template, a template argument T takes the place of Object and enables static type check- ing (§27.2). 22.7 Advice [1] Use read more..

  • Page - 679

    This page intentionally left blank read more..

  • Page - 680

    23 Templates Your quote here. – B. Stroustrup • Introduction and Overview • A Simple String Template Defining a Template; Template Instantiation • Type Checking Type Equivalence; Error Detection • Class Template Members Data Members; Member Functions; Member Type Aliases; static Members; Member Types; Member Templates; Friends • Function Templates Function Template Arguments; Function Template read more..

  • Page - 681

    666 Templates Chapter 23 used for a template need not be part of an inheritance hierarchy. Built-in types are acceptable and very common as template arguments. The composition offered by templates is type-safe (no object can be implicitly used in a way that disagrees with its definition), but unfortunately, a template’s requirements on its arguments cannot be simply and directly read more..

  • Page - 682

    Section 23.1 Introduction and Overview 667 Chapter 26, Instantiation, presents issues related to generation of template specialization (instances) and name binding: §26.2 T emplate Instantiation: The rules for when and how a compiler generates specializations from a template definition and how to specify them manually. §26.3 Name Binding: The rules for determining to which entity a name read more..

  • Page - 683

    668 Templates Chapter 23 23.2 A Simple String Template Consider a string of characters. A string is a class that holds characters and provides operations such as subscripting, concatenation, and comparison that we usually associate with the notion of a ‘‘string.’’ We would like to provide that behavior for many different kinds of characters. For exam- ple, strings of signed read more..

  • Page - 684

    Section 23.2 A Simple String Template 669 Except for the special syntax of its name, String<char> works exactly as if it had been defined using the definition of class String in §19.3. Making String a template allows us to provide the facilities we had for String of char for String s of any kind of character. For example, if we use the standard- library map and the read more..

  • Page - 685

    670 Templates Chapter 23 given suitable template arguments; the language mechanisms for doing that generation (instantia- tion (§26.2) and specialization (§25.3)) don’t care much whether a class or a function is generated. So, unless otherwise stated, the rules for templates apply equally to class templates and function templates. Templates can also be defined as aliases (§23.6), b ut read more..

  • Page - 686

    Section 23.2.1 Defining a Template 671 specific template arguments. For functions, we can also use overloading to provide different defini- tions for different argument types (§23.5.3). It is not possible to overload a class template name, so if a class template is declared in a scope, no other entity can be declared there with the same name. For example: template<typename read more..

  • Page - 687

    672 Templates Chapter 23 generated for a simple < or [] is often a single machine instruction, which is both much faster than any function call and smaller than the code needed to invoke a function and receive its result. 23.3 Type Checking Template instantiation takes a template plus a set of template arguments and generates code from them. Because so much information read more..

  • Page - 688

    Section 23.3 Type Checking 673 and catch obvious errors. For example, Container<int>() is obviously false because int does not have a subscript operator. I will return to the design of concepts (§24.3), consider techniques for sup- porting concepts in code (§24.4), and give an example of a set of useful concepts (§24.3.2). For now, just note that C++ does not directly support read more..

  • Page - 689

    674 Templates Chapter 23 23.3.2 Error Detection A template is defined and then later used in combination with a set of template arguments. When the template is defined, the definition is checked for syntax errors and possibly also for other errors that can be detected in isolation from a particular set of template arguments. For example: template<typename T> struct Link { read more..

  • Page - 690

    Section 23.3.2 Error Detection 675 void f(const List<int>& li, const List<Rec>& lr) { li.print_all(); lr.print_all(); } The li.print_all() checks out fine, but lr.print_all() gives a type error because there is no << output operator defined for Rec . The earliest that errors relating to a template parameter can be detected is at the first point of use of the template read more..

  • Page - 691

    676 Templates Chapter 23 23.4.2 Member Functions As for an ‘‘ordinary class,’’ a non-static member function of a class template can be defined in-class or outside the class. For example: template<typename T> struct X { void mf1() { /* ... */ } // defined in-class void mf2(); }; template<typename T> void X<T>::mf2() { /* ... */ } // defined out of class Similarly, read more..

  • Page - 692

    Section 23.4.4 static Members 677 static int m3; static void f1() { /* ... */ } static void f2(); }; template<typename T> int X<T>::m1 = 88; // error : two initializers template<typename T> int X<T>::m3 = 99; template<typename T> void X::<T>::f2() { /* ... */ } As for non-template classes, a const or conexpr static data member of literal type can be initialized in-class read more..

  • Page - 693

    678 Templates Chapter 23 The out-of-class definition of a member enumeration is only allowed for an enumeration for which we know the underlying type (§8.4). As usual, the enumerators of a non-class enum are placed in the scope of the enumeration; that is, for a member enumeration, the enumerators are in the scope of its class. 23.4.6 Member Templates A class or a class read more..

  • Page - 694

    Section 23.4.6 Member Templates 679 Using the (old) () syntax would leave us open to narrowing errors. For example: template<typename Scalar> class complex { // old style Scalar re, im; public: complex() :re(0), im(0) { } template<typename T> complex(T rr, T ii =0) :re(rr), im(ii) { } complex(const complex&) = default; // copy constr uctor template<typename T> complex(const read more..

  • Page - 695

    680 Templates Chapter 23 23.4.6.3 Use of Nesting In general, it is a good idea to keep information as local as possible. That way, a name is easier to find and less likely to interfere with anything else in a program. This line of thinking leads to types being defined as members. Doing so is often a good idea. However, for members of class tem- plates we must read more..

  • Page - 696

    Section 23.4.6.3 Use of Nesting 681 But what if a nested class is not considered an implementation detail? That is, what if we need an associated type that is meant for a variety of users? Consider: template<typename T , typename A> class List { public: class Iterator { Link<T> ∗ current_position; public: // ... usual iterator operations ... }; Iterator<T,A> begin(); read more..

  • Page - 697

    682 Templates Chapter 23 We could make fct a template and generate separate specializations for each allocator. Howev er, that would generate a new specialization for every use of Iterator , so this could lead to significant code bloat [Tsafrir,2009]. Again, we solve the problem by moving Link out of the class template: template<typename T> struct Iterator { Link<T> ∗ read more..

  • Page - 698

    Section 23.4.7 Friends 683 template<typename T> Vector<T> operator ∗(const Matrix<T>& m, const V ector<T>& v) { Vector<T> r; // ... use m.v[i] and v.v[i] for direct access to elements ... return r; } Friends do not affect the scope in which the template class is defined, nor do they affect the scope in which the template is used. Instead, friend functions and read more..

  • Page - 699

    684 Templates Chapter 23 Unfortunately, there is no way of saying that Link<X> should only be a friend of List<X> . Friend classes are designed to allow the representation of small clusters of closely related con- cepts. A complicated pattern of friendship is almost certainly a design error. 23.5 Function Templates For many people, the first and most obvious use of read more..

  • Page - 700

    Section 23.5 Function Templates 685 This does not introduce any new overhead. Better yet, the standard-library swap() uses move semantics, so we may see a speedup (§35.5.2). In this example, operator < is used for comparison. However, not every type has a < operator. This limits the use of this version of sort() , but the limitation is easily avoided by adding an argu- read more..

  • Page - 701

    686 Templates Chapter 23 template<typename T , int max> struct Buffer { T buf[max]; public: // ... }; template<typename T , int max> T& lookup(Buffer<T,max>& b, const char ∗ p); Record& f(Buffer<string,128>& buf, const char ∗ p) { return lookup(buf,p); // use the lookup() where T is string and i is 128 } Here, lookup() ’s T is deduced to be string and max is read more..

  • Page - 702

    Section 23.5.1 Function Template Arguments 687 explicitly qualified function template syntax. Default template arguments can be used to simplify explicit qualification in some cases (§25.2.5.1). 23.5.2 Function Template Argument Deduction A compiler can deduce a type template argument, T or TT , and a non-type template argument, I , from a template function argument with a type composed read more..

  • Page - 703

    688 Templates Chapter 23 23.5.2.1 Reference Deduction It can be useful to have different actions taken for lvalues and rvalues. Consider a class for holding an {integer,pointer} pair: template<typename T> class Xref { public: Xref(int i, T ∗ p) // store a pointer: Xref is the owner :index{i}, elem{p}, owner{true} {} Xref(int i, T& r) // store a pointer to r, owned by read more..

  • Page - 704

    Section 23.5.2.1 Reference Deduction 689 template<typename TT, typename A> unique_ptr<TT> make_unique(int i, A&& a) // simple var iant of make_shared (§34.3.2) { return unique_ptr<TT>{new TT{i,forward<A>(a)}}; } We want make_unique<T>(arg) to construct a T from an arg without making any spurious copies. To do that, it is essential that the lvalue/rvalue distinction is read more..

  • Page - 705

    690 Templates Chapter 23 [1] Find the set of function template specializations (§23.2.2) that will take part in overload resolution. Do this by considering each function template and deciding which template arguments, if any, would be used if no other function templates or functions of the same name were in scope. For the call sqrt(z) , this makes sqrt<double>(complex<double>) read more..

  • Page - 706

    Section 23.5.3.1 Ambiguity Resolution 691 23.5.3.1 Ambiguity Resolution We could resolve the two ambiguities by explicit qualification: void f() { max<int>('a',1); // max<int>(int(’a’),1) max<double>(2.7,4); // max<double>(2.7,double(4)) } Alternatively, we could add suitable declarations: inline int max(int i, int j) { return max<int>(i,j); } inline double max(int i, double d) { read more..

  • Page - 707

    692 Templates Chapter 23 template<typename Iter> typename Iter::value_type mean(Iter rst, Iter last); // #1 template<typename T> T mean(T ∗,T∗); // #2 void f(vector<int>& v, int ∗ p, int n) { auto x = mean(v.begin(),v.end()); // OK: call #1 auto y = mean(p,p+n); // OK: call #2 } This works: both initializations succeed. But why didn’t we get an error when trying to read more..

  • Page - 708

    Section 23.5.3.2 Argument Substitution Failure 693 void f(vector<int>& v, int ∗ p, int n) { auto x = mean(v.begin(),v.end()); // OK: call #1 auto y = mean(p,p+n); // error : ambiguous } The declaration of mean() #1 is fine for mean(p,p+n) . The compiler does not start to instantiate the body of that mean() and eliminate it because of the type error. Here, the result is read more..

  • Page - 709

    694 Templates Chapter 23 struct Index { operator int(); // ... }; void f(vector<int>& v, shor t s, Index i) { int i1 = get_nth<int>(v,2); // exact match int i2 = get_nth<int>(v,s); // standard conversion: short to int int i3 = get_nth<int>(v,i); // user-defined conversion: Index to int } This notation is sometimes called explicit specialization (§23.5.1). 23.6 read more..

  • Page - 710

    Section 23.6 Template Aliases 695 template<> struct int_exact_traits<16> { using type = short; }; template<int N> using int_exact = typename int_exact_traits<N>::type; // define alias for convenient notation int_exact<8> a = 7; // int_exact<8> is an int with 8 bits If specializations did not get used through the alias, we couldn’t claim that int_exact was simply an read more..

  • Page - 711

    696 Templates Chapter 23 and // file user2.cpp: #include "out.h" // use out() That is, the definition of out() and all declarations on which it depends are #include d in sev eral dif- ferent compilation units. It is up to the compiler to generate code when needed (only) and to opti- mize the process of reading redundant definitions. This strategy treats template read more..

  • Page - 712

    Section 23.7 Source Code Organization 697 subtly change the meaning of a definition: // file user1.cpp: #include "out.h" // use out() and // file user4.cpp: #de ne std MyLib #include "out.c" // use out() This sneaky and error-prone use of a macro changes the definition of out so that user4.cpp ’s defini- tion differs from user1.cpp ’s. This is an error, but read more..

  • Page - 713

    698 Templates Chapter 23 Note that I took the opportunity to simplify the interface to accum() compared to std::accumu- late() . The generality that is a key attribute of good template libraries can be seen as a source of complexity in a particular application. I suspect that I would not use this technique for standard-library templates. Those are stable over years and known read more..

  • Page - 714

    24 Generic Programming Now is a good time to put your work on a firm theoretical basis. – Sam Morgan • Introduction • Algorithms and Lifting • Concepts Discovering a Concept; Concepts and Constraints • Making Concepts Concrete Axioms; Multi-argument Concepts; Value Concepts; Constraints Checks; Template Defini- tion Checking • Advice 24.1 Introduction What are templates for? In other read more..

  • Page - 715

    700 Generic Programming Chapter 24 The first and most common use of templates is to support generic programming, that is, pro- gramming focused on the design, implementation, and use of general algorithms. Here, ‘‘general’’ means that an algorithm can be designed to accept a wide variety of types as long as they meet the algorithm’s requirements on its arguments. The read more..

  • Page - 716

    Section 24.2 Algorithms and Lifting 701 How do we get from a function doing specific operations on specific data to an algorithm doing more general operations on a variety of data types? The most effective way of getting a good algo- rithm is to generalize from one – and preferably more – concrete example. Such generalization is called lifting: that is, lifting a read more..

  • Page - 717

    702 Generic Programming Chapter 24 To do so, I write some pseudo code: // pseudo code: T sum(data) // somehow parameter ize by the value type and the container type { Ts=0 while (not at end) { s = s + current value get next data element } return s } To make this concrete, we need three operations to access the ‘‘container’’ data structure: • Not at end • Get read more..

  • Page - 718

    Section 24.2 Algorithms and Lifting 703 To use the handcrafted singly-linked list, we need to provide an iterator for it. Given a few opera- tions, a Node ∗ can be the iterator: struct Node { Node ∗ next; int data; }; Node ∗ operator++(Node ∗ p) { return p >next; } int operator ∗(Node∗ p) { return p >data; } Node ∗ end(lst) { return nullptr; } void read more..

  • Page - 719

    704 Generic Programming Chapter 24 We now use the argument op to combine element values with the accumulator. For example: double ad[] = {1,2,3,4}; double s1 = accumulate(ad,ad+4,0.0,std::plus<double>); // as before double s2 = accumulate(ad,ad+4,1.0,std::multiply<double>); The standard library provides common operations, such as plus and multiply , as function objects to be used as read more..

  • Page - 720

    Section 24.3.1 Discovering a Concept 705 what does it take to be a character in such a character string class? An experienced designer will have a small number of likely answers to that question and start the design based on those. How- ev er, let us consider how we might answer it from first principles. We proceed through three stages of analysis: [1] First, we read more..

  • Page - 721

    706 Generic Programming Chapter 24 cases. Having assignment means that an algorithm can use temporary variables of its argument type, create containers of objects of an argument type, etc. It does not imply that we cannot use const to specify interfaces. For example: template<typename T> bool operator==(const String<T>& s1, const String<T>& s2) { if (s1.size()!=s2.siz e()) read more..

  • Page - 722

    Section 24.3.1 Discovering a Concept 707 But does it make sense to leave out ordering (<) for String ? Consider how we use strings. The desired use of a template (such as String ) should determine its requirements on its arguments. We do compare strings extensively, and in addition we use comparisons indirectly when we sort sequences of strings, we put strings into sets, read more..

  • Page - 723

    708 Generic Programming Chapter 24 24.3.2 Concepts and Constraints A concept is not an arbitrary collection of properties. Most lists of properties of a type (or a set of types) do not define a coherent and useful concept. To be useful as a concept, a list of requirements has to reflect the needs of a set of algorithms or a set of operations of a template class. read more..

  • Page - 724

    Section 24.3.2 Concepts and Constraints 709 struct Red_black_balance { // ... template<typename Node> static void add_ xup(Node ∗ x); template<typename Node> static void touc h(Node ∗ x); template<typename Node> static void detach (Node ∗ x); }; Obviously, we’d like to say what’s required of node_base ’s arguments, but a balancer is not meant to be a widely used and easily understood read more..

  • Page - 725

    710 Generic Programming Chapter 24 Ordered<X>() returns true , the compilation proceeds, generating exactly the code it would have done without the assert. Otherwise, the error message is produced. At first glance, this looks rather reasonable for a workaround. I’d rather have said: template<Ordered C> class String { // ... }; However, that is for the future, so let us read more..

  • Page - 726

    Section 24.4 Making Concepts Concrete 711 template<typename T> constexpr bool Regular() { return Semiregular<T>() && Equality_comparable<T>(); } Equality_comparable gives us == and != . Semiregular is the concept that express the notion of a type that doesn’t hav e unusual technical restrictions: template<typename T> constexpr bool Semiregular() { return Destructible<T>() read more..

  • Page - 727

    712 Generic Programming Chapter 24 have preferred for a constraints check to be guaranteed to be done by the compiler at the point of the first call, but that is impossible without language changes. • We can forget to insert a constraints check (especially for a function template). • The compiler does not check that a template implementation uses only the properties read more..

  • Page - 728

    Section 24.4 Making Concepts Concrete 713 24.4.1 Axioms As in mathematics, an axiom is something we can’t prove. It is something we assume to be true. In the context of requirements for template arguments, we use ‘‘axiom’’ in that sense to refer to semantic properties. We use an axiom to state what a class or an algorithm assumes about its set of inputs. An read more..

  • Page - 729

    714 Generic Programming Chapter 24 24.4.2 Multi-argument Concepts When looking at a single-argument concept and applying it to a type, it looks very much as if we are doing conventional type checking and that the concept is the type of a type. That’s part of the story, but only a part. Often, we find that relationships among argument types are essential for cor- rect read more..

  • Page - 730

    Section 24.4.2 Multi-argument Concepts 715 Multi-argument concepts are particularly common and useful when specifying generic algorithms. This is also the area where you find the greatest number of concepts and the greatest need to spec- ify new concepts (as opposed to picking ‘‘standard ones’’ from a catalog of common concepts). The variations among well-defined types appear to read more..

  • Page - 731

    716 Generic Programming Chapter 24 concepts in the standard library. They should go in a separate namespace to avoid interfering with possible future language features and alternative implementations of the idea of concepts. I use namespace Estd , but that may be an alias (§14.4.2). Here are a few constraints checks that you might find useful: • Input_iterator<X> : X is read more..

  • Page - 732

    Section 24.4.5 Template Definition Checking 717 24.4.5 Template Definition Checking A constraints-check template ensures that a type provides the properties required by the concept. If the implementation of a template in fact uses more properties than its concepts guarantee, we may get type errors. For example, the standard-library nd() requires a pair of input iterators as argu- ments, read more..

  • Page - 733

    718 Generic Programming Chapter 24 • A default constructor • A copy constructor and a copy assignment • Operators == and != • A prefix operator ++ • A type Value_type<Iterator> • A prefix operator ∗ • The ability to assign the result of ∗ to a Value_type<Iterator> • The ability to assign a Value_type<Iterator> to the result of ∗ This is slightly read more..

  • Page - 734

    Section 24.4.5 Template Definition Checking 719 Using a relatively small and well-specified set of concepts makes the task manageable. The tests can and should be completely compile-time. Note that this simple specification and checking strategy leads to nd() requiring its iterator argument to have a Value_type type function (§28.2). That allows pointers to be used as iterators. For read more..

  • Page - 735

    This page intentionally left blank read more..

  • Page - 736

    25 Specialization It ain’t what you don’t know that gets you into trouble. It’s what you know for sure that just ain’t so. – Mark Twain • Introduction • Template Parameters and Arguments Types as Arguments; Values as Arguments; Operations as Arguments; Templates as Argu- ments; Default Template Arguments • Specialization Interface Specialization; The Primary Template; Order of read more..

  • Page - 737

    722 Specialization Chapter 25 This chapter and the following two present simple examples of the advanced and/or specialized language features supporting techniques aimed at uncompromised flexibility and performance. Many of these techniques are primarily developed for and used by library implementers. Like most programmers, I prefer to forget about the more advanced techniques most of the read more..

  • Page - 738

    Section 25.2.1 Types as Arguments 723 f(1); // T deduced to be int f<double>(1); // T is double f<complex<double>>(1); // T is complex<double> X<double> x1; // T is double X<complex<double>> x2; // T is complex<double> A type argument is unconstrained; that is, there is nothing in the interface of a class that constrains it to be a certain kind of read more..

  • Page - 739

    724 Specialization Chapter 25 25.2.2 Values as Arguments A template parameter that is not a type or a template is called a value parameter and an argument passed to it a value argument. For example, integer arguments come in handy for supplying sizes and limits: template<typename T , int max> class Buffer { T v[max]; public: Buffer() { } // ... }; Buffer<char,128> cbuf; read more..

  • Page - 740

    Section 25.2.2 Values as Arguments 725 constexpr int max = 200; void f(int i) { Buffer<int,i> bx; // error : constant expression expected Buffer<int,max> bm; // OK: constant expression // ... } Conversely, a value template parameter is a constant within the template so that an attempt to change the value of a parameter is an error. For example: template<typename T , int read more..

  • Page - 741

    726 Specialization Chapter 25 How do we supply comparison criteria for Key s? • We can’t hardwire a comparison criterion into the container because the container can’t (in general) impose its needs on the element types. For example, by default, the map uses < for comparison, but not all Key shav ea < that we would want to use. • We can’t hardwire an ordering read more..

  • Page - 742

    Section 25.2.3 Operations as Arguments 727 comparison criterion, we can supply it as a function object (§3.4.3): map<string,int> m1; // use the default comparison (less<string>) map<string,int,std::greater<string>> m2; // compare using greater<str ing>() Function objects can carry state. For example: Complex_compare f3 {"French",3}; // make a compar ison object (§25.2.5) read more..

  • Page - 743

    728 Specialization Chapter 25 template<typename T , template<typename> class C> class Xrefd { C<T> mems; C<T ∗> refs; // ... }; template<typename T> using My_vec = vector<T>; // use default allocator Xrefd<Entry,My_vec> x1; // store cross references for Entrys in a vector template<typename T> class My_container { // ... }; Xrefd<Record,My_container> x2; // store read more..

  • Page - 744

    Section 25.2.5 Default Template Arguments 729 template<typename K ey, Class V, typename Compare = std::less<Key>> class map { public: explicit map(const Compare& comp ={}); // ... }; map<string,int> m1; // will use less<string> for comparisons map<string,int,less<string>> m2; // same type as m1 struct No_case { // define operator()() to do case-insensitive str ing compar read more..

  • Page - 745

    730 Specialization Chapter 25 The technique of supplying a policy through a template argument and then defaulting that argu- ment to supply the most common policy is almost universal in the standard library (e.g., §32.4). Curiously enough, it is not used for basic_string (§23.2, Chapter 36) comparisons. Instead, the standard-library string relies on char_traits (§36.2.2). Similarly, the read more..

  • Page - 746

    Section 25.3 Specialization 731 template arguments provided where they are used. Such alternative definitions of a template are called user-defined specializations, or simply user specializations. Consider likely uses of a Vector : template<typename T> class Vector { // general vector type T ∗ v; int sz; public: Vector(); explicit Vector(int); T& elem(int i) { return v[i]; } T& read more..

  • Page - 747

    732 Specialization Chapter 25 The Vector<void ∗> is a complete specialization. That is, there is no template parameter to spec- ify or deduce when we use the specialization; Vector<void ∗> is used for Vector s declared like this: Vector<void ∗>vpv; To define a specialization that is used for every Vector of pointers and only for Vector s of pointers, we can read more..

  • Page - 748

    Section 25.3 Specialization 733 to implement all lists of pointers is an example of the general technique of minimizing code bloat by maximizing the amount of shared code. Some compilers are getting smart enough to perform this particular optimization without help from the programmer, but the technique is generally applicable and useful. Variants of the technique of using a single read more..

  • Page - 749

    734 Specialization Chapter 25 For complex<double> , that same optimization applies. In addition, conversions from complex< oat> and complex<long double> are provided (as described in §23.4.6): template<> class complex<double> { public: constexpr complex(double re = 0.0, double im = 0.0); constexpr complex(const complex< oat>&); explicit constexpr complex(const complex<long read more..

  • Page - 750

    Section 25.3.2 The Primary Template 735 25.3.2 The Primary Template When we have both a general definition of a template and specializations defining implementations for specific sets of template arguments, we refer to the most general template as the primary tem- plate. The primary template defines the interface for all specializations (§iso.14.5.5). That is, the primary template read more..

  • Page - 751

    736 Specialization Chapter 25 List<int ∗> li; template<typename T> class List<T ∗>{ // error : specialization used before defined // ... }; Here, List was specialized for int ∗ after List<int ∗> had been used. It is essential that every use of a template for a given set of template arguments be implemented by the same specialization. If not, the type system read more..

  • Page - 752

    Section 25.3.4.1 Specialization and Overloading 737 25.3.4.1 Specialization and Overloading Consider the Shell sort from §12.5 and §23.5. Those versions compare elements using < and swap elements using detailed code. A better definition would be: template<typename T> bool less(T a, T b) { return a<b; } template<typename T> void sort(Vector<T>& v) { const size_t n = v.siz e(); read more..

  • Page - 753

    738 Specialization Chapter 25 template<> bool less(const char ∗ a, const char ∗ b) { return strcmp(a,b)<0; } I prefer this shorter form of declaration. We can go further still. With this last version the distinc- tion between specialization and overloading has become razor thin and largely irrelevant, so we can simply write: bool less(const char ∗ a, const char ∗ b) { read more..

  • Page - 754

    Section 25.3.4.2 Specialization That Is Not Overloading 739 int max2(int) { return INT_MAX; } char max2(char) { return INT_MAX; } template<typename Iter> Iter my_algo2(Iter p) { auto x = max2(Value_type<Iter>{}); // works for the types for which we overload max2() // ... } 25.4 Advice [1] Use templates to improve type safety; §25.1. [2] Use templates to raise the level of read more..

  • Page - 755

    This page intentionally left blank read more..

  • Page - 756

    26 Instantiation For every complex problem, there is an answer that is clear, simple, and wrong. – H. L. Mencken • Introduction • Template Instantiation When Is Instantiation Needed?; Manual Control of Instantiation • Name Binding Dependent Names; Point-of-Definition Binding; Point-of-Instantiation Binding; Multiple Instantiation Points; Templates and Namespaces; Overaggressive ADL; Names from read more..

  • Page - 757

    742 Instantiation Chapter 26 • Is it a name from a base class in a hierarchy? • Is it a name from a named namespace? • Is it a global name? This chapter discusses such questions related to name binding and considers their implications for programming styles. • Templates were introduced in §3.4.1 and §3.4.2. • Chapter 23 gives a detailed introduction to templates and the read more..

  • Page - 758

    Section 26.2.1 When Is Instantiation Needed? 743 26.2.1 When Is Instantiation Needed? It is necessary to generate a specialization of a class template only if the class’s definition is needed (§iso.14.7.1). In particular, to declare a pointer to some class, the actual definition of a class is not needed. For example: class X; X ∗ p; // OK: no definition of X needed Xa; read more..

  • Page - 759

    744 Instantiation Chapter 26 26.2.2 Manual Control of Instantiation The language does not require any explicit user action to achieve template instantiation. However, it does provide two mechanisms to help the user take control when needed. The need sometimes arises from a wish to • optimize the compile-and-link process by eliminating redundant replicated instantiations, or • know read more..

  • Page - 760

    Section 26.2.2 Manual Control of Instantiation 745 void foo(MyVector<int>& v) { // ... use the vector in here ... } The ‘‘elsewhere’’ might look something like this: #include "MyVector.h" template class MyVector<int>; // instantiate in this translation unit; use this point of instantiation In addition to generating specializations for all members of a class, the read more..

  • Page - 761

    746 Instantiation Chapter 26 // ... #include<quad.h> void f(std::vector<Quad>& v) { Quad c = sum(v); } The innocent-looking template function sum() depends on several names that are not explicitly specified in its definition, such as tracing , cerr , and the + operator. In this example, + is defined in <quad.h> : Quad operator+(Quad,Quad); Importantly, nothing related to Quad read more..

  • Page - 762

    Section 26.3.1 Dependent Names 747 Consequently, a function call is said to depend on a template argument if and only if one of these conditions holds: [1] The type of the actual argument depends on a template parameter T according to the type deduction rules (§23.5.2), for e xample, f(T(1)) , f(t) , f(g(t)) , and f(&t) , assuming that t is a T . [2] The function called read more..

  • Page - 763

    748 Instantiation Chapter 26 We can avoid such awkward use of typename by introducing a type alias (§23.6). For example: template<typename T> using Value_type<T> = typename T::v alue_type; template<typename Container> void fct2(Container& c) { Value_type<Container> v1 = c[7]; // OK // ... } Naming a member template after a . (dot), > ,or :: requires similar use of the keyword read more..

  • Page - 764

    Section 26.3.2 Point-of-Definition Binding 749 template<typename T> T f(T a) { ++x; // OK: x is in scope ++y; // error : no y in scope, and y doesn’t depend on T return a; // OK: a is dependent } int y; int z = f(2); If a declaration is found, that declaration is used even if a ‘‘better’’ declaration might be found later. For example: void g(double); void read more..

  • Page - 765

    750 Instantiation Chapter 26 void h(int i) { extern void g(double); f(i); } // point of declaration for f<int> The point of instantiation for f<int>() is outside h() . This is essential to ensure that the g() called in f() is the global g(int) rather than the local g(double) . An unqualified name used in a template defini- tion can never be bound to a local name. read more..

  • Page - 766

    Section 26.3.3 Point-of-Instantiation Binding 751 Had the point of instantiation been after f() the call c.sort() would have failed to find the definition of Container<int> . Relying on template arguments to make dependencies explicit simplifies our thinking about the template code and even allows us to access local information. For example: void fff() { struct S { int a,b; }; read more..

  • Page - 767

    752 Instantiation Chapter 26 In this trivial case, there is a lot to be said for removing the dependence on the global name cout . However, in general, as illustrated by sort() , adding parameters can make the code much more ver- bose without necessarily making it easier to understand. Also, if the name-binding rules for templates were radically more restrictive than the read more..

  • Page - 768

    Section 26.3.4 Multiple Instantiation Points 753 For ff() we have two instantiation points. For the first call, we could generate the specialization at the initialization of x1 and get g(N::X,int) called. Alternatively, we could wait and generate the spe- cialization at the end of the translation unit and get g(N::X,char) called. Consequently, the call ff(N::X{},1.1) is an error. It read more..

  • Page - 769

    754 Instantiation Chapter 26 26.3.6 Overaggressive ADL Argument-dependent lookup (often referred to as ADL) is very useful to avoid verbosity (§14.2.4). For example: #include <iostream> int main() { std::cout << "Hello, world" << endl;// OK because of ADL } Without argument-dependent lookup, the endl manipulator would not be found. As it is, the com- piler notices that the read more..

  • Page - 770

    Section 26.3.6 Overaggressive ADL 755 template<typename In, typename Out> Out copy(In p1, In p2, Out q) { static_assert(Input_iterator<In>(), "copy(): In is not an input iterator"); static_assert(Output_iterator<Out>(), "copy(): Out is not an output iterator"); static_assert(Assignable<Value_type<Out>,Value_type<In>>(), "copy(): value type mismatch"); // ... } Better still, read more..

  • Page - 771

    756 Instantiation Chapter 26 26.3.7 Names from Base Classes When a class template has a base class, it can access names from that base. As for other names, there are two distinct possibilities: • The base class depends on a template argument. • The base class does not depend on a template argument. The latter case is simple and treated just like base classes in classes read more..

  • Page - 772

    Section 26.3.7 Names from Base Classes 757 void h(X<B> x) { x.f(); } Why doesn’t g(2) call B::g(char) (as in the previous example)? Because g(2) isn’t dependent on the template parameter T . It is therefore bound at the point of definition; names from the template argument T (which happens to be used as a base class) are not (yet) known and therefore not con- sidered. If read more..

  • Page - 773

    758 Instantiation Chapter 26 It is easy to forget to qualify names from a base, and the qualified code often looks a bit verbose and messy. Howev er, the alternative would be that a name in a template class would sometimes bind to a base class member and sometimes to a global entity depending on the template argument. That is not ideal either, and the language read more..

  • Page - 774

    27 Templates and Hierarchies Euclid’s and Beethoven’s Fifth; knowing just one of them marks you as semi-educated. – Stan Kelley-Bootle • Introduction • Parameterization and Hierarchy Generated Types; Template Conversions • Hierarchies of Class Templates Templates as Interfaces • Template Parameters as Base Classes Composing Data Structures; Linearizing Class Hierarchies • Advice 27.1 read more..

  • Page - 775

    760 Templates and Hierarchies Chapter 27 From a design perspective, the two approaches are close enough to deserve a common name. Since both allow an algorithm to be expressed once and applied to a variety of types, people refer to both as polymorphic (from Greek ‘‘many shapes’’). To distinguish them, what virtual functions provide is called run-time polymorphism, and what read more..

  • Page - 776

    Section 27.2 Parameterization and Hierarchy 761 Ct<A> cta; // specialization for A Ct<B> ctb; // specialization for B Given that, we can use f() , g() , and h() on the variables cta and ctb , using the implementations of Ct<A> and Ct<B> , respectively. I used an explicit specialization (§23.5.3.4) to show that implemen- tations can vary from what the primary template read more..

  • Page - 777

    762 Templates and Hierarchies Chapter 27 • If the implementations of generated or derived classes differ only through a parameter or differ only in a few special cases, templates have an advantage. Irregular implementations can be expressed through derived classes or specializations. • If the actual types of objects used cannot be known at compile time, a class hierarchy is read more..

  • Page - 778

    Section 27.2.1 Generated Types 763 class Triangle : public Shape { // ... }; void f(set<Shape ∗>& s) { // ... s.insert(new Triangle{p1,p2,p3}); } void g(set<Circle ∗>& s) { f(s); // error, type mismatch: s is a set<Circle*>, not a set<Shape*> } This won’t compile because there is no built-in conversion from set<Circle ∗>& to set<Shape ∗>&. Nor read more..

  • Page - 779

    764 Templates and Hierarchies Chapter 27 In the example above, assume that a Shape is an abstract class with size 4 and that Circle adds a center and a radius. Then sizeof(Circle)>siz eof(Shape) and when we look at the layout of image we find something like this: user() view: image[0] image[1] image[2] image[3] maul() view: p[0] p[1] p[2] p[3] When maul() tries to invoke a read more..

  • Page - 780

    Section 27.2.2 Template Conversions 765 template<typename T> template<typename T2> Ptr<T>::operator Ptr<T2>() { return Ptr<T2>{p}; } The return -statement will compile if and only if p (which is a T ∗) can be an argument to the Ptr<T2>(T2 ∗) constructor. Therefore, if T ∗ can be implicitly converted into a T2 ∗, the Ptr<T> to Ptr<T2> conversion will read more..

  • Page - 781

    766 Templates and Hierarchies Chapter 27 template<typename Color_scheme , typename Canvas> class Triangle : public Shape { // ... }; void user() { auto p = new Triangle<RGB,Bitmapped>{{0,0},{0,60},{30,sqr t(60 ∗60 30 ∗30)}}; // ... } Something along this line is often the first idea (after seeing something like vector<T> ) that a pro- grammer used to object-oriented programming read more..

  • Page - 782

    Section 27.3.1 Templates as Interfaces 767 27.3.1 Templates as Interfaces A template class can be used to provide a flexible and type-safe interface to a common implementa- tion. The vector from §25.3 is a good e xample of this: template<typename T> class Vector<T ∗> : private Vector<void ∗> { // ... }; In general, this technique can be used to provide type-safe interfaces read more..

  • Page - 783

    768 Templates and Hierarchies Chapter 27 There are more alternatives, but consider: template<typename N> struct Node_base { // doesn’t know about Val (the user data) N ∗ left_child; N ∗ right_child; Node_base(); void add_left(N ∗ p) { if (left_child==nullptr) left_child = p; else // ... } // ... }; template<typename V al> struct Node : Node_base<Node<Val>> { // use derived read more..

  • Page - 784

    Section 27.4.1 Composing Data Structures 769 if (i++%2) // choose where to insert root.add_left(p); else root.add_right(p); } } However, it is not easy for a user to keep the structure of a tree reasonable. Typically, we would like to let the tree take care of that by implementing a tree-balancing algorithm. However, to bal- ance a tree so that you can search it efficiently, read more..

  • Page - 785

    770 Templates and Hierarchies Chapter 27 template<typename V al, typename Balance> struct Search_node : public Node_base<Search_node<Val, Balance>, Balance> { Val val; // user data search_node(Val v): val(v) {} }; Balance is mentioned twice here because it is part of the node type and because Node_base needs to make an object of type Balance : template<typename N, typename read more..

  • Page - 786

    Section 27.4.1 Composing Data Structures 771 The layout of a node is compact, and we can easily inline all performance-critical functions. What we achieved by the slightly elaborate set of definitions was type safety and ease of composition. This elaboration delivers a performance advantage compared to every approach that introduces a void ∗ into the data structure or function read more..

  • Page - 787

    772 Templates and Hierarchies Chapter 27 typed abstract syntax trees. It uses template parameters as base classes extensively, both as an implementation aid (implementation inheritance) and to provide abstract interfaces in the classical object-oriented way (interface inheritance). The design addresses a difficult set of criteria, includ- ing compactness of nodes (there can be many millions read more..

  • Page - 788

    Section 27.4.2 Linearizing Class Hierarchies 773 Node Expr Stmt Decl Var impl::Node impl::Expr impl::Stmt impl::Decl impl::Var For the full set of classes the chain of derivation becomes: impl::Var > impl::Decl<impl::Var> > impl::Stmt<impl::Var> > impl::Expr<impl::Var> > impl::Node<impl::Var> > ipr::Var > ipr::Decl > ipr::Stmt > ipr::Expr > ipr::Node This is read more..

  • Page - 789

    774 Templates and Hierarchies Chapter 27 An expression (Expr)isa Node that has a type: struct ipr::Expr : Node { virtual const Type& type() const = 0; protected: Expr(Category_code c) : Node(c) { } }; Obviously, this is quite a generalization of C++ because it implies that even statements and types have types: it is an aim of the IPR to represent all of C++ without read more..

  • Page - 790

    Section 27.4.2 Linearizing Class Hierarchies 775 struct ipr::Var : Category<var_cat, Dec l> { }; Basically, Category is a notational aid with the effect of deriving Var from Decl and giving the Cate- gory_code used to optimize Node type identification: template<Category_code Cat, typename T = Expr> struct Category : T { protected: Category() : T(Cat) { } }; Every data member is a read more..

  • Page - 791

    776 Templates and Hierarchies Chapter 27 template<typename S> struct impl::Stmt : S { ipr::Unit_location unit_locus; // logical position in translation unit ipr::Source_location src_locus; // source file, line, and column ref_sequence<ipr::Annotation> notes; const ipr::Unit_location& unit_location() const override { return unit_locus; } const ipr::Source_location& sour ce_location() const override { read more..

  • Page - 792

    Section 27.5 Advice 777 27.5 Advice [1] When having to express a general idea in code, consider whether to represent it as a template or as a class hierachy; §27.1. [2] A template usually provides common code for a variety of arguments; §27.1. [3] An abstract class can completely hide implementation details from users; §27.1. [4] Irregular implementations are usually best read more..

  • Page - 793

    This page intentionally left blank read more..

  • Page - 794

    28 Metaprogramming Trips to fairly unknown regions should be made twice; once to make mistakes and once to correct them. – John Steinbeck • Introduction • Type Functions Type Aliases; Type Predicates; Selecting a Function; Traits • Control Structures Selection; Iteration and Recursion; When to Use Metaprogramming • Conditional Definition: Enable_if Use of Enable_if ; Implementing Enable_if read more..

  • Page - 795

    780 Metaprogramming Chapter 28 There are two main reasons for using metaprogramming techniques: • Improved type safety: We can compute the exact types needed for a data structure or algo- rithm so that we don’t need to directly manipulate low-level data structures (e.g., we can eliminate many uses of explicit type conversion). • Improved run-time performance: We can compute read more..

  • Page - 796

    Section 28.1 Introduction 781 The ordering indicates the level of complexity, with implications for the difficulty of the task, the difficulty of debugging, and the likelihood of error. So, metaprogramming is a combination of ‘‘meta’’ and programming: a metaprogram is a com- pile-time computation yielding types or functions to be used at run time. Note that I don’t say read more..

  • Page - 797

    782 Metaprogramming Chapter 28 template<typename T , int N> struct Array_type { using type = T; static const int dim = N; // ... }; This Array_type is not a standard-library function or even a particularly useful function. I just used it as an excuse to show how to write a simple multi-argument, multi-return-value type function. It can be used like this: using Array = read more..

  • Page - 798

    Section 28.2 Type Functions 783 The standard-library template conditional is a compile-time selector between two alternatives. If its first argument evaluates to true , the result (presented as the member type ) is the second argument; otherwise, the result is the third argument. §28.3.1.1 shows how conditional is implemented. In this case, Obj_holder<X> ’s type is defined to be read more..

  • Page - 799

    784 Metaprogramming Chapter 28 On_heap and Scoped provide good examples of how generic programming and template metapro- gramming require us to devise uniform interfaces to different implementations of a general idea (here, the idea of allocation of an object). Both On_heap and Scoped can be used as members as well as local variables. On_heap always places its object on the free read more..

  • Page - 800

    Section 28.2.1.1 When Not to Use an Alias 785 if (p) { p >f(7); // ... } It is important that we don’t enter the block if p is the nullptr . We are using the test to see if p is valid. Similarly, we might want to test to see if a type is valid. For example: conditional< is_integral<T>::value , make_unsigned<T>, Error<T> >::type Here, we test if T is read more..

  • Page - 801

    786 Metaprogramming Chapter 28 template<typename T> void copy(T ∗ p, const T ∗ q, int n) { if (std::is_pod<T>::value) memcpy(p,q,n); // use optimized memory copy else for (int i=0; i!=n; ++i) p[i] = q[i]; // copy individual values } Here, we try to optimize the copy by using the (supposedly optimal) standard-library function mem- cpy() when we can treat the objects as read more..

  • Page - 802

    Section 28.2.2 Type Predicates 787 I capitalize the names of these type functions to avoid confusion with the standard-library versions. In addition, I keep them in a separate namespace (Estd). We can define our own type predicates. For example: template<typename T> constexpr bool Is_big() { return 100<sizeof(T); } We could use this (rather crude) notion of ‘‘big’’ like read more..

  • Page - 803

    788 Metaprogramming Chapter 28 Classes with member functions computing some value are the most general and flexible mechanism for computation in template metaprogramming. Conditional is a mechanism for compile-time programming. In particular, this means that the condition must be a constant expression. Note the parentheses around sizeof(int)>4 ; without those, we would have gotten a read more..

  • Page - 804

    Section 28.2.4 Traits 789 template<typename T> using Iterator_category= typename std::iterator_trait<T>::iterator_category; The example cleans up nicely: template<typename Iter> Iter search(Iter p, iter q, Value_type<Iter> val) { Difference_type<Iter> m = q p; // ... } I suspect that traits are currently overused. Consider how to write the previous example without any mention of traits read more..

  • Page - 805

    790 Metaprogramming Chapter 28 and Select are for selecting types. They are not simply compile-time equivalents to if and switch ev en though they can appear to be when they are used to choose among function objects (§3.4.3, §19.2.2). 28.3.1.1 Selecting between Two Types It is surprisingly simple to implement Conditional , as used in §28.2. The conditional template is part of read more..

  • Page - 806

    Section 28.3.1.2 Compile Time vs. Run Time 791 struct Square { constexpr int operator()(int i) { return i ∗i; } }; struct Cube { constexpr int operator()(int i) { return i ∗i∗i; } }; We might try the familiar if -statement: if (My_cond<T>()) using Type = Square; // error : declaration as if-statement branch else using Type = Cube; // error : declaration as if-statement read more..

  • Page - 807

    792 Metaprogramming Chapter 28 class Nil {}; template<int I, typename T1 =Nil, typename T2 =Nil, typename T3 =Nil, typename T4 =Nil> struct select; template<int I, typename T1 =Nil, typename T2 =Nil, typename T3 =Nil, typename T4 =Nil> using Select = typename select<I,T1,T2,T3,T4>::type; // Specializations for 0-3: template<typename T1, typename T2, typename T3, typename T4> struct read more..

  • Page - 808

    Section 28.3.1.3 Selecting among Several Types 793 template<typename T , typename ... Cases> // final case: N==0 struct select<0,T,Cases...> { using type = T; }; template<unsigned N, typename... Cases> using Select = typename select<N,Cases...>::type; 28.3.2 Iteration and Recursion The basic techniques for calculating a value at compile time can be illustrated by a factorial func- read more..

  • Page - 809

    794 Metaprogramming Chapter 28 28.3.2.1 Recursion Using Classes Iteration involving more complicated state or more elaborate parameterization can be handled using classes. For example, the factorial program becomes: template<int N> struct Fac { static const int value = N ∗Fac<N 1>::value; }; template<> struct Fac<1> { static const int value = 1; }; constexpr int x7 = read more..

  • Page - 810

    Section 28.3.3 When to Use Metaprogramming 795 Similarly, a more complex condition would almost equalize the number of characters used. The fundamental difference is that I have to write typename and ::type to use the standard’s terminology. That exposes the template implementation technique. I would like to hide that, and the macro does. However, if many people need to read more..

  • Page - 811

    796 Metaprogramming Chapter 28 template<typename T> class Smart_pointer { // ... T& operator ∗(); // return reference to whole object if (Is_class<T>()) T ∗ operator >(); // syntax error // ... } However, that does not work. C++ does not provide an if that can select among definitions based on a general condition. But, as with Conditional and Select (§28.3.1), there is a w read more..

  • Page - 812

    Section 28.4 Conditional Definition: Enable_if 797 In this case, the elaboration of the declaration of operator >() with Enable_if simply changes the kind of error we get from examples, such as p >real() : • If we unconditionally declare operator >() , we get a ‘‘ > used on a non-class pointer’’ error at instantiation time for the definition of read more..

  • Page - 813

    798 Metaprogramming Chapter 28 constructor. The problem is that I ‘‘forgot’’ to tell the compiler that the Iter type should be an itera- tor. Howev er, that can be done: template<typename T> class vector<T> { public: vector(size_t n, const T& va l); // n elements of type T with value val template<typename Iter, typename =Enable_if<Input_iterator<Iter>(),Iter>> read more..

  • Page - 814

    Section 28.4.2 Implementing Enable_if 799 28.4.2 Implementing Enable_if The implementation of Enable_if is almost trivial: template<bool B, typename T = void> struct std::enable_if { typedef T type; }; template<typename T> struct std::enable_if<false , T> {}; // no ::type if B==false template<bool B, typename T = void> using Enable_if = typename std::enable_if<B,T>::type; Note that we read more..

  • Page - 815

    800 Metaprogramming Chapter 28 question ‘‘Can we call f(x) if x is of type X ?’’ Defining has_f to answer that question gives an opportunity to demonstrate some of the techniques used and some of the scaffolding/boilerplate code provided internally in many template metaprogramming libraries (including parts of the stan- dard library). First, define the usual class plus specialization read more..

  • Page - 816

    Section 28.4.4 More Enable_if Examples 801 Note that decltype() does not evaluate its operand. We managed to turn what looked like a type error into the value false . It would have been sim- pler if the language had provided a primitive (built-in) operation for doing that conversion; for example: is_valid()); // can f(x) be compiled? However, a language cannot provide read more..

  • Page - 817

    802 Metaprogramming Chapter 28 template<typename Iter, typename Val> Enable_if<!Has_not_equals<Iter>(),Iter> nd(Iter rst, Iter last, Val v) { while (!( rst==last) && !( ∗ rst==v)) ++ rst; return rst; } Such ad hoc overloading easily gets messy and unmanageable. For example, try adding versions that use != for the value comparison (that is, ∗ rst!=v , rather than !( ∗ read more..

  • Page - 818

    Section 28.5 A Compile-Time List: Tuple 803 Base ∗ base() { return static_cast<Base ∗>(this); } const Base ∗ base() const { return static_cast<const Base ∗>(this); } Tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4) :Base{t2,t3,t4}, x{t1} { } }; So, a Tuple of four elements (often referred to as a 4-tuple) is a Tuple of three elements (a 3-tuple) read more..

  • Page - 819

    804 Metaprogramming Chapter 28 using Base = Tuple<T2, T3>; Base ∗ base() { return static_cast<Base ∗>(this); } const Base ∗ base() const { return static_cast<const Base ∗>(this); } Tuple(const T1& t1, const T2& t2, const T3& t3) :Base{t2, t3}, x{t1} { } }; These declarations are rather repetitive and follow the simple pattern of the first Tuple (the 4-tuple). That read more..

  • Page - 820

    Section 28.5.1 A Simple Output Function 805 template<typename T1, typename T2, typename T3> void print_elements(ostream& os, const Tuple<T1,T2,T3>& t) { os << t.x << ", "; print_elements(os, ∗t.base()); } template<typename T1, typename T2> void print_elements(ostream& os, const Tuple<T1,T2>& t) { os << t.x << ", "; print_elements(os, ∗t.base()); } read more..

  • Page - 821

    806 Metaprogramming Chapter 28 { 1.1 42, a } { 1.2,3,5,7 } { 1.2,3,5 } { 1.2,3 } {1.2 } {} 28.5.2 Element Access As defined, Tuple has a variable number of elements of potentially differing types. We would like to access those elements efficiently and without the possibility of type system violations (i.e., with- out using casts). We can imagine a variety of schemes, read more..

  • Page - 822

    Section 28.5.2 Element Access 807 template<typename Ret> struct getNth<Ret,0> { template<typename T> static Ret& ge t(T& t) { return t.x; } }; Basically, getNth is a special-purpose for -loop, implemented by recursing N 1 times. The member functions are static because we don’t really want any objects of class getNth . That class is only used as a place to hold Ret and N read more..

  • Page - 823

    808 Metaprogramming Chapter 28 const Tuple<double , int, char> xx {1.1, 422, 'a'}; char cc = get<2>(xx); // OK: reading from const cout << "xx: " << xx << "\n"; get<2>(xx) = 'x'; // error : xx is const To handle const Tuple s, we have to add const versions of get() and getNth ’s get() . For example: template<typename Ret, int N> struct read more..

  • Page - 824

    Section 28.5.3 make_tuple 809 template<typename T1, typename T2, typename T3, typename T4> Tuple<T1, T2, T3, T4> make_tuple(const T1& t1, const T2& t2, const T3& t3, const T4& t4) { return Tuple<T1, T2, T3, T4>{t1, t2, t3,t4}; } // ... and the other four make_Tuples ... Given make_tuple() , we can write: auto xxx = make_Tuple(1.2,3,'x',1223); cout << "xxx: " << xxx read more..

  • Page - 825

    810 Metaprogramming Chapter 28 string name = "target"; printf("The value of %s is %P\n",name,Point{34,200}); printf("The value of %s is %g\n",7); The first call of printf() works as intended, but the second call has two problems: the format specifi- cation %s refers to C-style strings, and printf() will not interpret the std::string argument correctly. Furthermore, there read more..

  • Page - 826

    Section 28.6.1 A Type-Safe printf() 811 std::cout << ∗s++; } throw std::runtime_error("extra arguments pro vided to printf"); } This printf() finds and prints the first non-format argument, ‘‘peels of f’’ that argument, and then calls itself recursively. When there are no more non-format arguments, it calls the first (simpler) printf() . Ordinary characters (i.e., not % read more..

  • Page - 827

    812 Metaprogramming Chapter 28 std::cout << value; // use first non-for mat argument return printf(++s, args...); // do a recursive call with the tail of the argument list } std::cout << ∗s++; } throw std::runtime_error("extra arguments pro vided to printf"); } The standard library provides std::is_integral and std::is_ oating_point , but you’d hav e to craft read more..

  • Page - 828

    Section 28.6.2 Technical Details 813 the beginning and work our way through to what we want. The implementation of Tuple demon- strates that technique (§28.5). We can find the type of the first element and access it using that, then we can (recursively) proceed to the next argument. If we want to, we can give the appearance of indexed access using something like read more..

  • Page - 829

    814 Metaprogramming Chapter 28 28.6.3 Forwarding One of the major uses of variadic templates is forwarding from one function to another. Consider how to write a function that takes as arguments something to be called and a possibly empty list of arguments to give to the ‘‘something’’ as arguments: template<typename F , typename ... T> void call(F&& f, T&&... read more..

  • Page - 830

    Section 28.6.3 Forwarding 815 call(g1<int>,1); call(g1<const c har ∗>,"hello"); call(g1<double>,1.2); call(g1d,1.2); call(g1d,"No way!"); // error : wrong argument type for g1d() call(g1d,1.2,"I can't count"); // error : too many arguments for g1d() call(g2<double ,string>,1,"world!"); int i = 99; // testing with lvalues const char ∗ p = "Tr read more..

  • Page - 831

    816 Metaprogramming Chapter 28 template<typename... VValues> tuple& operator=(const tuple<VValues...>& other) // assignment { m_head = other.head(); tail() = other.tail(); return ∗this; } // ... protected: Head m_head; private: Add_reference<Head> head() { return m_head; } Add_const_reference<const Head> head() const { return m_head; } inherited& tail() { return ∗this; } const inherited& tail() read more..

  • Page - 832

    Section 28.6.4 The Standard-Library tuple 817 for example, using the standard-library make_tuple() : template<typename... Types> tuple<Types...> make_tuple(Types&&... t) // simplified (§iso.20.4.2.4) { return tuple<Types...>(t...); } string s = "Hello"; vector<int> v = {1,22,3,4,5}; auto x = make_tuple(s,v,1.2); The standard-library tuple has many more members than listed in the read more..

  • Page - 833

    818 Metaprogramming Chapter 28 However, note how it wastefully lets get<N>() count from 0 to N . We can now write a << for tuple : std::ostream& operator << (ostream& os, const tuple<>&) // the empty tuple { return os << "{}"; } template<typename T0, typename ...T> ostream& operator<<(ostream& os, const tuple<T0, T...>& t) // a nonempty read more..

  • Page - 834

    Section 28.7 SI Units Example 819 if (speed == 10_m/20_s) // OK: the units match // ... Quantity<MpS2> acceleration = distance/square(time); // MpS2 means m/(s*s) cout << "speed==" << speed << " acceleration==" << acceleration << "\n"; Units provide a type system for physical values. As shown, we can use auto to hide types when we want to read more..

  • Page - 835

    820 Metaprogramming Chapter 28 template<typename U1, typename U2> struct Uminus { using type = Unit<U1::m U2::m, U1::kg U2::kg, U1::s U2::s>; }; template<typename U1, U2> using Unit_minus = typename Uminus<U1,U2>::type; Unit_plus and Unit_minus are simple type functions (§28.2) on Unit s. 28.7.2 Quantity s A Quantity is a value with an associated Unit : template<typename U> struct read more..

  • Page - 836

    Section 28.7.2 Quantity s 821 Multiplication Quantity s require addition of their Unit s. Similarly, division of Quantity s subtrac- tion of their Unit s. For example: template<typename U1, typename U2> Quantity<Unit_plus<U1,U2>> operator ∗(Quantity<U1> x, Quantity<U2> y) { return Quantity<Unit_plus<U1,U2>>{x.val ∗y.val}; } template<typename U1, typename U2> read more..

  • Page - 837

    822 Metaprogramming Chapter 28 28.7.3 Unit Literals Thanks to the type aliases for the most common units, we can now write: auto distance = Quantity<M>{10}; // 10 meters auto time = Quantity<S>{20}; // 20 seconds auto speed = distance/time; // .5 m/s (meters per second) That’s not bad, but it is still verbose compared to code that conventionally simply leaves the units read more..

  • Page - 838

    Section 28.7.3 Unit Literals 823 I use underscores in my units _s and _m so as not to get in the way of the standard library pro- viding the shorter and nicer s and m suffixes. 28.7.4 Utility Functions To finish the job (as defined by the initial example), we need the utility function square() , the equal- ity operator, and the output operator. Defining square() is read more..

  • Page - 839

    824 Metaprogramming Chapter 28 template<typename U> ostream& operator<<(ostream& os, Quantity<U> v) { return os << v.va l << suf x(U::m,"m") << suf x(U::kg,"kg") << suf x(U::s,"s"); } Finally, we can write: auto distance = 10_m; // 10 meters auto time = 20_s; // 20 seconds auto speed = distance/time; // .5 m/s (meters per second) if (speed read more..

  • Page - 840

    Section 28.8 Advice 825 [14] Use variadic templates when you need a function that takes a variable number of arguments of a variety of types; §28.6. [15] Don’t use variadic templates for homogeneous argument lists (prefer initializer lists for that); §28.6. [16] Use variadic templates and std::move() where forwarding is needed; §28.6.3. [17] Use simple metaprogramming to implement read more..

  • Page - 841

    This page intentionally left blank read more..

  • Page - 842

    29 A Matrix Design Never express yourself more clearly than you are able to think. – Niels Bohr • Introduction Basic Matrix Uses; Matrix Requirements •A Matrix Template Construction and Assignment; Subscripting and Slicing • Matrix Arithmetic Operations Scalar Operations; Addition; Multiplication • Matrix Implementation slice ; Matrix Slices; Matrix_ref ; Matrix List Initialization; Matrix Access; read more..

  • Page - 843

    828 A Matrix Design Chapter 29 29.1.1 Basic Matrix Uses Matrix<T,N> is an N -dimensional matrix of some value type T . It can be used like this: Matrix<double ,0> m0 {1}; // zero dimensions: a scalar Matrix<double ,1> m1 {1,2,3,4}; // one dimension: a vector (4 elements) Matrix<double ,2> m2 { // two dimensions (4*3 elements) {00,01,02,03}, // row 0 {10,11,12,13}, // row read more..

  • Page - 844

    Section 29.1.1 Basic Matrix Uses 829 Matrix<T,N> has its number of dimensions (its order() ) specified as a template argument (here, N ). Each dimension has a number of elements (its extent() ) deduced from the initializer list or specified as a Matrix constructor argument using the () notation. The total number of elements is referred to as its size() . For example: read more..

  • Page - 845

    830 A Matrix Design Chapter 29 29.1.2 Matrix Requirements Before proceeding with an implementation, consider what properties we might like to hav e: • N dimensions, where N is a parameter that can vary from 0 to many, without specialized code for every dimension. • N -dimensional storage is useful in general, so the element type can be anything we can store (like a vector read more..

  • Page - 846

    Section 29.2 A Matrix Template 831 29.2 A Matrix Template To giv e an overview, here is the declaration of Matrix with its most interesting operations: template<typename T , siz e_t N> class Matrix { public: static constexpr size_t order = N; using value_type = T; using iterator = typename std::vector<T>::iterator; using const_iterator = typename std::vector<T>::const_iterator; read more..

  • Page - 847

    832 A Matrix Design Chapter 29 Using a vector<T> to hold the elements relieves us from concerns of memory management and exception safety. A Matrix_slice holds the sizes necessary to access the elements as an N -dimen- sional matrix (§29.4.2). Think of it as a gslice (§40.5.6) specialized for our Matrix . A Matrix_ref (§29.4.3) behaves just like a Matrix except that it refers to read more..

  • Page - 848

    Section 29.2.1 Construction and Assignment 833 Without that =delete , that last definition would have been accepted. Finally, we hav e to be able to construct from a Matrix_ref , that is, from a reference to a Matrix or a part of a Matrix (a submatrix): template<typename T , siz e_t N> template<typename U> Matrix<T,N>::Matrix(const Matrix_ref<U,N>& x) :desc{x.desc}, read more..

  • Page - 849

    834 A Matrix Design Chapter 29 template<typename... Args> // m(i,j,k) subscripting with integers Enable_if<Matrix_impl::Requesting_element<Args...>(), T&> operator()(Args... args); template<typename... Args> Enable_if<Matrix_impl::Requesting_element<Args...>(), const T&> operator()(Args... args) const; template<typename... Args> // m(s1,s2,s3) subscripting with slices read more..

  • Page - 850

    Section 29.2.2 Subscripting and Slicing 835 Matrix<int> m2 { {01,02,03}, {11,12,13}, {21,22,23} }; auto m22 = m(slice{1,2},slice{0,3}); Now m22 is a Matrix<int,2> with the value { {11,12,13}, {21,22,23} } The first (row) subscript slice{1,2} selects the last two rows, and the second (column) subscript slice{0,3} selects all elements in the columns. The return type for a () with slice read more..

  • Page - 851

    836 A Matrix Design Chapter 29 The implementations of row() , column() , and operator()() are presented in §29.4.5. The imple- mentations of const versions of these functions are basically the same as those of their non-const versions. The key difference is that const versions return results with const elements. 29.3 Matrix Arithmetic Operations So, we can create Matrix es, copy them, read more..

  • Page - 852

    Section 29.3.1 Scalar Operations 837 29.3.1 Scalar Operations A scalar arithmetic operation simply applies its operation and right-hand operand to each element. For example: template<typename T , siz e_t N> Matrix<T,N>& Matrix<T ,N>::operator+=(const T& val) { return apply([&](T& a) { a+=v al; } ); // using a lambda (§11.4) } This apply() applies a function (or a function read more..

  • Page - 853

    838 A Matrix Design Chapter 29 template<typename T , siz e_t N> template<typename M, typename F> Enable_if<Matrix_type<M>(),Matrix<T,N>&> Matrix<T,N>::apply(M& m, F f) { assert(same_extents(desc,m.descriptor())); // make sure sizes match for (auto i = begin(), j = m.begin(); i!=end(); ++i, ++j) f( ∗i,∗j); return ∗this; } Now operator+() is easily defined: read more..

  • Page - 854

    Section 29.3.2 Addition 839 Such operations look exactly like their Matrix equivalents. There is no difference between Matrix and Matrix_ref element access: the difference between Matrix and Matrix_ref is in the initialization and ownership of elements. Subtraction, multiplication, etc., by scalars and the handling of Matrix_ref s are just repetition of the techniques used for addition. 29.3.3 read more..

  • Page - 855

    840 A Matrix Design Chapter 29 Note that the declaration of res initializes its elements to T{} , which is zero for numeric types, so that the += starts out from zero. The N-by-M matrix times M-by-P matrix is handled similarly: template<typename T> Matrix<T,2> operator ∗(const Matrix<T,2>& m1, const Matrix<T,2>& m2) { const size_t n = m1.extent(0); const size_t m = read more..

  • Page - 856

    Section 29.4.1 slice() 841 29.4.1 slice() A simple slice as used for slice subscripting describes a mapping from an integer (subscript) to an element location (index) in terms of three values: struct slice { slice() :start( 1), length( 1), stride(1) { } explicit slice(size_t s) :start(s), length( 1), stride(1) { } slice(size_t s, size_t l, size_t n = 1) :start(s), length(l), stride(n) read more..

  • Page - 857

    842 A Matrix Design Chapter 29 template<size_t N> template<typename... Dims> size_t Matrix_slice<N>::operator()(Dims... dims) const { static_assert(sizeof...(Dims) == N, ""); size_t args[N] { size_t(dims)... }; // Copy arguments into an array return inner_product(args,args+N,strides.begin(),siz e_t(0)); } Subscripting must be efficient. This is a simplified algorithm that needs to be read more..

  • Page - 858

    Section 29.4.3 Matrix_ref 843 private: Matrix_slice<N> desc; // the shape of the matrix T ∗ ptr; // the first element in the matrix }; A Matrix_ref simply points to the elements of ‘‘its’’ Matrix . Obviously, a Matrix_ref should not out- live its Matrix . For example: Matrix_ref<double ,1> user() { Matrix<double ,2> m = {{1,2}, {3,4}, {5,6}}; return m.row(1); } auto mr read more..

  • Page - 859

    844 A Matrix Design Chapter 29 Matrix_init<T,N> simply has Matrix_init<T,N 1> as its member type: template<typename T , siz e_t N> struct Matrix_init { using type = initializer_list<typename Matrix_init<T,N 1>::type>; }; The N==1 is special. That is where we get to the (most deeply nested) initializer_list<T> : template<typename T> struct Matrix_init<T,1> { using read more..

  • Page - 860

    Section 29.4.4 Matrix List Initialization 845 template<size_t N, typename I, typename List> Enable_if<(N>1),void> add_extents(I& rst, const List& list) { assert(check_non_jagged(list)); ∗ rst = list.size(); add_extents<N 1>(++ rst, ∗list.begin()); } template<size_t N, typename I, typename List> Enable_if<(N==1),void> add_ex tents(I& rst, const List& list) { ∗ rst++ = read more..

  • Page - 861

    846 A Matrix Design Chapter 29 template<typename T , typename Vec> void add_list(const T ∗ rst, const T ∗ last, Vec& vec) { vec.insert(vec.end(), rst,last); } I use vec.insert(vec.end(), rst,last) because there is no push_back() that takes a sequence argument. 29.4.5 Matrix Access A Matrix provides access by row, column, slice (§29.4.1), and element (§29.4.3). A row() or col- umn() read more..

  • Page - 862

    Section 29.4.5 Matrix Access 847 Subscripting with integers is defined like this: template<typename T , siz e_t N> // subscripting with integers template<typename... Args> Enable_if<Matrix_impl::Requesting_element<Args...>(),T&> Matrix<T,N>::operator()(Args... args) { assert(Matrix_impl::check_bounds(desc, args...)); return ∗(data() + desc(args...)); } The check_bounds() predicate checks that the read more..

  • Page - 863

    848 A Matrix Design Chapter 29 The reason for using a predicate (Requesting_element) and the Enable_if() ‘‘hidden’’ within Request is to choose between the element and the slice subscript operators. The predicate used by the slice subscript operator looks like this: template<typename... Args> constexpr bool Requesting_slice() { return All((Conver tible<Argssiz e_t>() || read more..

  • Page - 864

    Section 29.4.6 Zero-Dimensional Matrix 849 template<typename T> class Matrix<T,0> { public: static constexpr size_t order = 0; using value_type = T; Matrix(const T& x) : elem(x) { } Matrix& operator=(const T& v alue) { elem = value; return ∗this; } T& operator()() { return elem; } const T& operator()() const { return elem; } operator T&() { return elem; } operator const read more..

  • Page - 865

    850 A Matrix Design Chapter 29 x = ⎡ ⎢ ⎢ ⎣ x1 ... xn ⎤ ⎥ ⎥ ⎦ , and b = ⎡ ⎢ ⎢ ⎣ b1 ... bn ⎤ ⎥ ⎥ ⎦ This system may have zero, one, or an infinite number of solutions, depending on the coefficients of the matrix A and the vector b . There are various methods for solving linear systems. We use a classic scheme, called Gaussian elimination read more..

  • Page - 866

    Section 29.5.1 Classical Gaussian Elimination 851 void classical_elimination(Mat2d& A, V ec& b) { const size_t n = A.dim1(); // traverse from 1st column to the next-to-last, filling zeros into all elements under the diagonal: for (siz e_t j = 0; j!=n 1; ++j) { const double pivot = A(j, j); if (pivot==0) throw Elim_failure(j); // fill zeros into each element under the diagonal read more..

  • Page - 867

    852 A Matrix Design Chapter 29 // look for a suitable pivot: for (siz e_t k = j+1; k!=n; ++k) if (abs(A(k,j)) > abs(A(pivot_row,j))) pivot_row = k; // swap the rows if we found a better pivot: if (pivot_row!=j) { A.swap_rows(j,pivot_row); std::swap(b(j),b(pivot_row)); } // elimination: for (siz e_t i = j+1; i!=n; ++i) { const double pivot = A(j,j); if (pivot==0) error("can't read more..

  • Page - 868

    Section 29.5.3 Testing 853 • A bug in the code (but, being optimists, we don’t think there are any) • An input that trips up classical_elimination() (using elim_with_partial_pivot() would minimize the chances of that) • Rounding errors However, our test is not as realistic as we’d like because genuinely random matrices are unlikely to cause problems for classical_elimination() . read more..

  • Page - 869

    854 A Matrix Design Chapter 29 impressive speedups (say, 30 times) on some systems by enabling more powerful optimization techniques. First, for simplicity, let us restrict ourselves to two-dimensional matrices of double- precision floating-point numbers: using Mat2d = Matrix<double ,2>; using Vec = Matrix<double ,1>; We define the result of multiplying a Mat2d by a Vec : struct read more..

  • Page - 870

    Section 29.5.4 Fused Operations 855 public: Matrix(const MVmulVadd& m) // initialize by result of m { // allocate elements, etc. mul_add_and_assign(this,&m.m,&m.v,&m.v2); } Matrix& operator=(const MVmulVadd& m) // assign the result of m to *this { mul_add_and_assign(this,&m.m,&m.v,&m.v2); return ∗this; } // ... }; Now U=M ∗V+W is automatically expanded to read more..

  • Page - 871

    856 A Matrix Design Chapter 29 [5] When designing a container template, carefully consider the requirements on the element type; §29.1.2. [6] Consider how the design might accommodate run-time checking (e.g., for debugging); §29.1.2. [7] If possible, design a class to mimic existing professional notation and semantics; §29.1.2. [8] Make sure that the design does not leak resources read more..

  • Page - 872

    Part IV The Standard Library This part describes the C++ standard library. The aim is to provide an understanding of how to use the library, to demonstrate generally useful design and programming techniques, and to show how to extend the library in the ways in which it was intended to be extended. Chapters 30 Standard-Library Overview 31 STL Containers 32 STL Algorithms 33 STL read more..

  • Page - 873

    858 The Standard Library Part IV ‘‘... I am just now beginning to discover the difficulty of expressing one’s ideas on paper. As long as it consists solely of description it is pretty easy; but where reasoning comes into play, to make a proper connection, a clearness & a moderate fluency, is to me, as I have said, a difficulty of which I had no idea read more..

  • Page - 874

    30 Standard-Library Overview Many secrets of art and nature are thought by the unlearned to be magical. – Roger Bacon • Introduction Standard-Library Facilities; Design Constraints; Description Style • Headers • Language Support initializer_list Support; Range-for Support • Error Handling Exceptions; Assertions; system_error • Advice 30.1 Introduction The standard library is the set of components read more..

  • Page - 875

    860 Standard-Library Overview Chapter 30 The standard library is rather large: its specification in the ISO C++ standard is 785 dense pages. And that is without describing the ISO C standard library, which is a part of the C++ stan- dard library (another 139 pages). To compare, the C++ language specification is 398 pages. Here, I summarize, relying heavily on tables, and read more..

  • Page - 876

    Section 30.1.1 Standard-Library Facilities 861 • A foundation for portability • A set of compact and efficient components that can be used as the foundation for perfor- mance-sensitive libraries and applications • A set of components enabling intra-library communications The design of the library is primarily determined by these three roles. These roles are closely related. For read more..

  • Page - 877

    862 Standard-Library Overview Chapter 30 For example, building the comparison criteria into a sort function is unacceptable because the same data can be sorted according to different criteria. This is why the C standard-library qsort() takes a comparison function as an argument rather than relying on something fixed, say, the < operator (§12.5). On the other hand, the overhead read more..

  • Page - 878

    Section 30.2 Headers 863 30.2 Headers The facilities of the standard library are defined in the std namespace and presented as a set of headers. The headers identify the major parts of the library. Thus, listing them gives an overview of the library. The rest of this subsection is a list of headers grouped by function, accompanied by brief expla- nations and annotated by read more..

  • Page - 879

    864 Standard-Library Overview Chapter 30 Algorithms <algorithm> General algorithms §32.2 <cstdlib> bsearch() , qsort() §43.7 A typical general algorithm can be applied to any sequence (§3.4.2, §32.2) of any type of element. The C standard library functions bsearch() and qsort() apply to built-in arrays with elements of types without user-defined copy constructors and destructors only read more..

  • Page - 880

    Section 30.2 Headers 865 Localization <locale> Represent cultural differences Chapter 39 <clocale> Represent cultural differences C-style <codecvt> Code conversion facets §39.4.6 A locale localizes differences such as the output format for dates, the symbol used to represent cur- rency, and string collation criteria that vary among different natural languages and cultures. Language read more..

  • Page - 881

    866 Standard-Library Overview Chapter 30 Concurrency <atomic> Atomic types and operations §41.3 <condition_variable> Waiting for an action §42.3.4 <future> Asynchronous task §42.4.4 <mutex> Mutual exclusion classes §42.3.1 <thread> Threads §42.2 C provides standard-library facilities of varying relevance to C++ programmers. The C++ standard library provides access to all such read more..

  • Page - 882

    Section 30.3 Language Support 867 Library Supported Language Features <new> new and delete §11.2 <typeinfo> typeid() and type_info §22.5 <iterator> Range-for §30.3.2 <initializer_list> initializ er_list §30.3.1 30.3.1 initializer_list Support A {} -list is converted into an object of type std::initializer_list<X> according to the rules described in §11.3. In <initializer_list> ,wefind read more..

  • Page - 883

    868 Standard-Library Overview Chapter 30 void f2(initializer_list<int> lst) { for (auto x : lst) cout << x << '\n'; } 30.3.2 Range-for Support A range-for statement is mapped to a for -statement using an iterator as described in §9.5.1. In <iterator> , the standard library provides std::begin() and std::end() functions for built-in arrays and for every type that provides read more..

  • Page - 884

    Section 30.4.1 Exceptions 869 Standard-Library Exceptions (continued) new T Throws bad_alloc if it cannot allocate memory for a T dynamic_cast<T>(r) Throws bad_cast if it cannot convert the reference r to a T typeid() Throws bad_typeid if it cannot deliver a type_info thread Throws system_error call_once() Throws system_error mutex Throws system_error condition_variable Throws system_error async() Throws read more..

  • Page - 885

    870 Standard-Library Overview Chapter 30 The standard-library exception hierarchy is rooted in class exception : class exception { public: exception(); exception(const exception&); exception& operator=(const exception&); virtual ˜exception(); virtual const char ∗ what() const; }; The what() function can be used to obtain a string that is supposed to indicate something about the error that read more..

  • Page - 886

    Section 30.4.1.2 Exception Propagation 871 Exception Propagation (§iso.18.8.5) exception_ptr Unspecified type used to point to exceptions ep=current_exception() ep is an exception_ptr to the current exception, or to no exception if there is no currently active exception; noexcept rethrow_exception(ep) Re-throw the exception pointed to by ep ; ep ’s contained pointer must not be nullptr ; read more..

  • Page - 887

    872 Standard-Library Overview Chapter 30 The intended use of nested_exception is as a base class for a class used by an exception handler to pass some information about the local context of an error together with a exception_ptr to the exception that caused it to be called. For example: struct My_error : runtime_error { My_error(const string&); // ... }; void my_code() { try { read more..

  • Page - 888

    Section 30.4.1.3 terminate() 873 terminate (§iso.18.8.3, §iso.18.8.4) h=get_terminate() h is the current terminate handler; noexcept h2=set_terminate(h) h becomes the current terminate handler; h2 is the previous terminate handler; noexcept terminate() Terminate the program; noreturn; noexcept uncaught_exception() Has an exception been thrown on the current thread and not yet been caught? noexcept Av oid read more..

  • Page - 889

    874 Standard-Library Overview Chapter 30 The name of the function (__func__) may also be included in the message. It can be a serious mistake to assume that the assert() is evaluated when it is not. For example, given a usual compiler setup, assert(p!=nullptr) will catch an error during debugging, but not in the final shipped product. For a way to manage assertions, see read more..

  • Page - 890

    Section 30.4.3.1 Error Codes 875 30.4.3.1 Error Codes When an error ‘‘bubbles up’’ from a lower level as an error code, we must handle the error it repre- sents or turn it into an exception. But first we must classify it: different systems use different error codes for the same problem, and different systems simply have different kinds of errors. error_code (§iso.19.5.2) read more..

  • Page - 891

    876 Standard-Library Overview Chapter 30 class error_code { public: // representation: {value,categor y} of type {int,const error_category*} }; An error_categor y is an interface to an object of a class derived from error_categor y . Therefore, an error_categor y is passed by reference and stored as a pointer. Each separate error_categor y is repre- sented by a unique object. Consider read more..

  • Page - 892

    Section 30.4.3.2 Error Categories 877 error_categor y (§iso.19.5.1.1) cat.˜error_categor y() Destructor; virtual; noexcept s=cat.name() s is the name of cat ; s is a C-style string; virtual; noexcept ec=cat.default_error_condition(n) ec is the error_condition for n in cat ; virtual; noexcept cat.equivalent(n,ec) Is ec.category()==cat and ec.value()==n ? ec is an error_condition ; virtual; noexcept read more..

  • Page - 893

    878 Standard-Library Overview Chapter 30 Exception Class system_error (§iso.19.5.6) system_error se {ec,s}; se holds {ec,s} ; ec is an error_code ; s is a string or a C-style string intended as part of an error message system_error se {ec}; se holds {ec} ; ec is an error_code system_error se {n,cat,s}; se holds {error_code{n,cat},s} ; cat is an error_categor y and n is an int representing read more..

  • Page - 894

    Section 30.4.3.5 Mapping Error Codes 879 30.4.3.5 Mapping Error Codes Making an error_categor y with a set of error_code s and at least one error_condition starts with defin- ing an enumeration with the desired error_code values. For example: enum class future_errc { broken_promise = 1, future_already_retrieved, promise_already_satis ed, no_state }; The meaning of these values is completely read more..

  • Page - 895

    880 Standard-Library Overview Chapter 30 For the error_code constructor and assignment that take a single error value, it is required that the argument be of the appropriate type for the error_categor y . For example, an argument intended to become the value() of an error_code of future_category() must be a future_errc . In particular, we can’t just use any int . For example: read more..

  • Page - 896

    Section 30.4.3.6 errc Error Codes 881 enum class errc Enumerators (§iso.19.5) (continued, continues) broken_pipe EPIPE connection_aborted ECONNABORTED connection_already_in_progress EALREADY connection_refused ECONNREFUSED connection_reset ECONNRESET cross_device_link EXDEV destination_address_required EDESTADDRREQ device_or_resource_busy EBUSY directory_not_empty ENOTEMPTY executable_format_error ENOEXEC le_exists EEXIST le_too_large EFBIG read more..

  • Page - 897

    882 Standard-Library Overview Chapter 30 enum class errc Enumerators (§iso.19.5) (continued) not_a_socket ENOTSOCK not_a_stream ENOSTR not_connected ENOTCONN not_enough_memory ENOMEM not_supported ENOTSUP operation_canceled ECANCELED operation_in_progress EINPROGRESS operation_not_permitted EPERM operation_not_supported EOPNOTSUPP operation_would_block EWOULDBLOCK owner_dead EOWNERDEAD permission_denied EACCES protocol_error EPROTO read more..

  • Page - 898

    Section 30.4.3.6 errc Error Codes 883 if (e==errc::broken_pipe) { // OK // ... } } 30.4.3.7 future_errc Error Codes Standard error_code s for the future_category() are defined by enum class future_errc : enum class future_errc Enumerators (§iso.30.6.1) broken_promise 1 future_already_retrieved 2 promise_already_satis ed 3 no_state 4 These codes are valid for the "future" category: future_category() read more..

  • Page - 899

    884 Standard-Library Overview Chapter 30 [13] Use static_assert() and assert() extensively; §30.4.2. [14] Do not assume that assert() is always evaluated; §30.4.2. [15] If you can’t use exceptions, consider <system_error> ; §30.4.3. read more..

  • Page - 900

    31 STL Containers It was new. It was singular. It was simple. It must succeed! – H. Nelson • Introduction • Container Overview Container Representation; Element Requirements • Operations Overview Member Types; Constructors, Destructor, and Assignments; Size and Capacity; Iterators; Element Access; Stack Operations; List Operations; Other Operations • Containers vector ; Lists; Associative read more..

  • Page - 901

    886 STL Containers Chapter 31 Containers can be categorized like this: • Sequence containers provide access to (half-open) sequences of elements. • Associative containers provide associative lookup based on a key. In addition, the standard library provides types of objects that hold elements while not offering all of the facilities of sequence containers or associative containers: • read more..

  • Page - 902

    Section 31.2 Container Overview 887 Ordered Associative Containers (§iso.23.4.2) C is the type of the comparison; A is the allocator type map<K,V,C,A> An ordered map from K to V ; a sequence of (K,V) pairs multimap<K,V,C,A> An ordered map from K to V ; duplicate keys allowed set<K,C,A> An ordered set of K multiset<K,C,A> An ordered set of K ; duplicate keys allowed read more..

  • Page - 903

    888 STL Containers Chapter 31 ‘‘ Almost Containers’’ T[N] A fixed-size built-in array: N contiguous elements of type T ; no siz e() or other member functions array<T,N> A fixed-size array of N contiguous elements of type T ; like the built-in array, but with most problems solved basic_string<C,Tr,A> A contiguously allocated sequence of characters of type C with text read more..

  • Page - 904

    Section 31.2.1 Container Representation 889 A list is most likely represented by a sequence of links pointing to the elements and the number of elements: rep list : v v v elements: A forward_list is most likely represented by a sequence of links pointing to the elements: rep forward_list : v v v elements: A map is most likely implemented as a (balanced) tree of nodes pointing to read more..

  • Page - 905

    890 STL Containers Chapter 31 A string might be implemented as outlined in §19.3 and §23.2; that is, for short string s the charac- ters are stored in the string handle itself, and for longer string s the elements are stored contiguously on the free-store (like vector elements). Like vector ,a string can grow into ‘‘free space’’ allocated to avoid repeated reallocations: rep read more..

  • Page - 906

    Section 31.2.2.1 Comparisons 891 31.2.2.1 Comparisons Associative containers require that their elements can be ordered. So do many operations that can be applied to containers (e.g., sort() and merge() ). By default, the < operator is used to define the order. If < is not suitable, the programmer must provide an alternative (§31.4.3, §33.4). The order- ing criterion must read more..

  • Page - 907

    892 STL Containers Chapter 31 Sorting using sort(fruit.begin(),fruit.end(),Nocase()) would yield something like fruit: Apple apple lemon Pear pear Assuming a character set in which uppercase letters precede lowercase letters, plain sort(fruit.begin(),fruit.end()) would give: fruit: Apple Pear apple lemon pear Beware that < on C-style strings (i.e., const char ∗s) compares pointer values (§7.4). read more..

  • Page - 908

    Section 31.3 Operations Overview 893 31.3 Operations Overview The operations and types provided by the standard containers can be summarized like this: value_type , size_type , difference_type , pointer , const_pointer , reference , const_reference iterator , const_iterator ,?reverse_iterator,?const_reverse_iterator, allocator_type begin() , end() , cbegin() , cend() ,?rbegin(),?rend(),?crbegin(),?crend(), = , == read more..

  • Page - 909

    894 STL Containers Chapter 31 •A multi ∗ associative container or a set does not provide [] or at() . •A forward_list does not provide insert() , erase() ,or emplace() ; instead, it provides the ∗_after operations. •A forward_list does not provide back() , push_back() , pop_back() ,or emplace_back() . •A forward_list does not provide reverse_iterator , const_reverse_iterator , rbegin() read more..

  • Page - 910

    Section 31.3 Operations Overview 895 Other entries are measures of the efficiency of the operations. A const entry means the opera- tion takes an amount of time that does not depend on the number of elements in the container; another conventional notation for constant time is O(1) . O(n) means the operation takes time propor- tional to the number of elements involved. A + read more..

  • Page - 911

    896 STL Containers Chapter 31 31.3.1 Member Types A container defines a set of member types: Member types (§iso.23.2, §iso.23.3.6.1) value_type Type of element allocator_type Type of memory manager size_type Unsigned type of container subscripts, element counts, etc. difference_type Signed type of difference between iterators iterator Behaves like value_type ∗ const_iterator Behaves like read more..

  • Page - 912

    Section 31.3.2 Constructors, Destructor, and Assignments 897 Constructors, Destructor, and Assignment (continued) C is a container; by default, a C uses the default allocator C::allocator_type{} C c {elem}; Initialize c from elem ; if C has an initializer-list constructor, prefer that; otherwise, use another constructor C c {c2}; Copy constructor: copy c2 ’s elements and allocator into c C c read more..

  • Page - 913

    898 STL Containers Chapter 31 void task(vector<int>&& v); vector<int> user(vector<int>& large) { vector<int> res; // ... task(move(large)); // transfer ownership of data to task() // ... return res; } 31.3.3 Size and Capacity The size is the number of elements in the container; the capacity is the number of elements that a container can hold before allocating more read more..

  • Page - 914

    Section 31.3.4 Iterators 899 31.3.4 Iterators A container can be viewed as a sequence either in the order defined by the containers iterator or in the reverse order. For an associative container, the order is based on the containers comparison cri- terion (by default < ): Iterators p=c.begin() p points to first element of c p=c.end() p points to one-past-last element of c read more..

  • Page - 915

    900 STL Containers Chapter 31 31.3.5 Element Access Some elements can be accessed directly: Element Access c.front() Reference to first element of c ; not for associative containers c.back() Reference to last element of c ; not for forward_list or associative containers c[i] Reference to the i th element of c ; unchecked access; not for lists or associative containers c.at(i) read more..

  • Page - 916

    Section 31.3.7 List Operations 901 31.3.7 List Operations Containers provide list operations: List Operations q=c.insert(p,x) Add x before p ; use copy or move q=c.insert(p,n,x) Add n copies of x before p ;if c is an associative container, p is a hint of where to start searching q=c.insert(p, rst,last) Add elements from [ rst :last) before p ; not for associative containers read more..

  • Page - 917

    902 STL Containers Chapter 31 finding the previous element in a forward_list given only an iterator. Instead, forward_iterator pro- vides operations, such as insert_after() , that operate after an element identified by an iterator. Simi- larly, unordered containers use emplace_hint() to provide a hint rather than ‘‘plain’’ emplace() . 31.3.8 Other Operations Containers can be compared read more..

  • Page - 918

    Section 31.4.1 vector 903 using size_type = /* implementation-defined */; using difference_type = /* implementation-defined */; using value_type = T; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = read more..

  • Page - 919

    904 STL Containers Chapter 31 chars.push_back(0); // end of previous word chars.push_back(c); words.push_back(&chars.back()); } else chars.push_back(c); } else in_word = false; } if (in_word) chars.push_back(0); // terminate last word if (max<chars.siz e()) { // oops: chars grew beyond capacity; the words are invalid // ... } chars.shrink_to_ t(); // release any sur plus capacity Had I not used read more..

  • Page - 920

    Section 31.4.1.2 vector and Nesting 905 The benefits of compactness and efficiency of access can be unintentionally compromised. Consider how to represent a two-dimensional matrix. There are two obvious alternatives: •A vector of vector s: vector<vector<double>> accessed by C-style double subscripting: m[i][j] • A specific matrix type, Matrix<2,double> (Chapter 29), that stores read more..

  • Page - 921

    906 STL Containers Chapter 31 31.4.1.3 vector and Arrays A vector is a resource handle. This is what allows it to be resized and enables efficient move semantics. However, that occasionally puts it at a disadvantage compared to data structures (such as built-in arrays and array ) that do not rely on storing elements separately from a handle. Keeping a sequence of elements on read more..

  • Page - 922

    Section 31.4.2 Lists 907 Compared to vector , subscripting could be painfully slow, so subscripting is not provided for lists. If necessary, use advance() and similar operations to navigate lists (§33.1.4). A list can be tra- versed using iterators: list provides bidirectional iterators (§33.1.2) and forward_list provides for- ward iterators (hence the name of that type of list). By read more..

  • Page - 923

    908 STL Containers Chapter 31 Operations for list<T> (§iso.23.3.5.5) p points to an element of lst or lst.end() lst.splice(p,lst2) Insert the elements of lst2 before p ; lst2 becomes empty lst.splice(p,lst2,p2) Insert the element pointed to by p2 in lst2 before p ; the element pointed to by p2 is removed from lst2 lst.splice(p,lst2,b,e) Insert the elements [b:e) from lst2 before p ; read more..

  • Page - 924

    Section 31.4.3 Associative Containers 909 31.4.3 Associative Containers Associative containers provide lookup based on keys. They come in two variants: • Ordered associative containers do lookup based on an ordering criterion, by default < (less than). They are implemented as balanced binary trees, usually red-black trees. • Unordered associative containers do lookup based on a hash read more..

  • Page - 925

    910 STL Containers Chapter 31 using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; class value_compare { /* operator()(k1,k2) does a key_compare()(k1,k2) */ }; // ... }; In addition to the read more..

  • Page - 926

    Section 31.4.3.1 Ordered Associative Containers 911 Associative Container Operations (continued) (§iso.23.4.4.1) p=c. nd(k) p points to the first element with key k or c.end() p=c.lower_bound(k) p points to the first element with key >=k or c.end() ; ordered containers only p=c.upper_bound(k) p points to the first element with key >k or c.end() ; ordered containers only read more..

  • Page - 927

    912 STL Containers Chapter 31 If that is not the desired behavior, we can use nd() and insert() directly: auto q = dictionary. nd("seal"); // lookup; don’t insert if (q==dictionary.end()) { cout << "entry not found"; dictionary.inser t(make_pair("seal","eats sh")); } else cout q >second; In fact, [] is little more than a convenient notation for insert() read more..

  • Page - 928

    Section 31.4.3.1 Ordered Associative Containers 913 To hav e a set<Record> , we need to provide a comparison function. For example: bool operator<(const Record& a, const Recor d& b) { return a.label<b.label; } Given that, we can write: set<Record> mr {{"duc k",10}, {"pork",12}}; void read_test() { for (auto& r : mr) { cout << '{' << r.label << ':' read more..

  • Page - 929

    914 STL Containers Chapter 31 void user() { cout <<"unordered: "; for (const auto& x : score1) cout << x << ", "; cout << "\nordered: "; for (const auto& x : score2) cout << x << ", "; } The visible difference is that iteration through a map is ordered and for an unordered_map it is not: unordered: {andy,7}, {al,9}, {bill, read more..

  • Page - 930

    Section 31.4.3.3 Constructing unordered_map s 915 The default equal_to<X> (§33.4) simply compares X values using == . The general (primary) template hash doesn’t hav e a definition. It is up to users of a type X to define hash<X> if needed. For common types, such as string , standard hash specializations are pro- vided, so the user need not provide them: Types with read more..

  • Page - 931

    916 STL Containers Chapter 31 unordered_map<K,T,H,E,A> Constructors (§iso.23.5.4) unordered_map m {{elem},n,hf,eql,a}; Construct m from the elem sofan initializer_list , using n buckets, the hash function hf , the equality function eql , and the allocator a unordered_map m {{elem},n,hf,eql}; unordered_map m {{elem},n,hf,eql,allocator_type{}}; unordered_map m {{elem},n,hf}; unordered_map m read more..

  • Page - 932

    Section 31.4.3.4 Hash and Equality Functions 917 size_t operator()(const Record& r) const { size_t h = 0; for (auto x : r.name) { h <<= d; h ˆ= toupper(x); } return h; } }; struct Nocase_equal { bool operator()(const Record& r, const Record& r2) const { if (r.name .size()!=r2.name .size()) return false; for (int i = 0; i<r.name .size(); ++i) if (toupper(r.name[i])!=toupper(r2.name[i])) read more..

  • Page - 933

    918 STL Containers Chapter 31 Given this hash function and equality function, we can define an unordered_set : unordered_set<Record,decltype(&hf),decltype(&eq)> m { { {"andy", 7}, {"al",9}, {"bill", 3}, {"barbara",12} }, hf, eq }; for (auto r : m) cout << "{" << r.name << ',' << r.v al << "}\n"; } I used decltype to avoid read more..

  • Page - 934

    Section 31.4.3.4 Hash and Equality Functions 919 template<> struct equal_to<Record> { bool operator()(const Record& r, const Record& r2) const { return r.name==r2.name && r.val==r2.val; } }; } unordered_set<Record> m1; unordered_set<Record> m2; The default hash and hashes obtained from it by using exclusive-or are often pretty good. Don’t rush to use homemade hash functions read more..

  • Page - 935

    920 STL Containers Chapter 31 You need to experiment to find a suitable load factor for a given set of elements and a particular hash function, but 70% (0.7) is often a good choice. Bucket Interface (§iso.23.2.5) n=c.bucket_count() n is the number of buckets in c (the size of the hash table); noexcept n=c.max_bucket_count() n is the largest possible number of elements in a read more..

  • Page - 936

    Section 31.5.1 stack 921 public: explicit stack(const C&); // copy from container explicit stack(C&& = C{}); // move from container // default copy, move, assignment, destructor template<typename A> explicit stack(const A& a); // default container, allocator a template<typename A> stack(const C& c, const A& a); // elements from c, allocator a template<typename A> read more..

  • Page - 937

    922 STL Containers Chapter 31 Often, vector is faster than deque and uses less memory. Elements are added to a stack using push_back() on the underlying container. Consequently, a stack cannot ‘‘overflow’’ as long as there is memory available on the machine for the container to acquire. On the other hand, a stack can underflow: void f() { stack<int> s; s.push(2); if read more..

  • Page - 938

    Section 31.5.2 queue 923 mess = q.front(); q.pop(); } // ser ve request } } 31.5.3 priority_queue A priority_queue is a queue in which each element is given a priority that controls the order in which the elements get to be the top() . The declaration of priority_queue is much like the declara- tion of queue with additions to deal with a comparison object and a couple of read more..

  • Page - 939

    924 STL Containers Chapter 31 This differs from the queue version (§31.5.2) in that Messages with higher priority will get served first. The order in which elements with equal priority come to the head of the queue is not defined. Tw o elements are considered of equal priority if neither has higher priority than the other (§31.2.2.1). Keeping elements in order isn’t free, read more..

  • Page - 940

    Section 31.6 Advice 925 [26] Prefer compact and contiguous data structures; §31.4.1.2. [27] Use emplace() to avoid having to pre-initialize elements; §31.4.1.3. [28] A list is relatively expensive to traverse; §31.4.2. [29] A list usually has a four-word-per-element memory overhead; §31.4.2. [30] The sequence of an ordered container is defined by its comparison object (by default < read more..

  • Page - 941

    This page intentionally left blank read more..

  • Page - 942

    32 STL Algorithms Form is liberating. – Engineer´s proverb • Introduction • Algorithms Sequences; Policy Arguments; Complexity • Nonmodifying Sequence Algorithms for_each() ; Sequence Predicates; count() ; nd() ; equal() and mismatch() ; search() • Modifying Sequence Algorithms copy() ; unique() ; remove() and replace() ; rotate() , random_shuf e() , and partition() ; Permuta- tions; ll() ; swap() read more..

  • Page - 943

    928 STL Algorithms Chapter 32 iterator, b2 , which is considered the start of a sequence holding sufficient elements for the algo- rithm, for example, as many elements as the first sequence: [b2:b2+(e b) ). Some algorithms, such as sort() , require random-access iterators, whereas many, such as nd() , only read their elements in order so that they can make do with a read more..

  • Page - 944

    Section 32.2.1 Sequences 929 if (target.siz e()<source .size()) thr ow out_of_rang e{"copy target too small"}; std::copy(source .begin(),source .end(),target.begin()); } This would simplify the definition of user() , make the second error impossible to express, and catch the first at run time: void user(vector<int>& v1, vector<int>& v2) { copy(v1,v2); // overflows will be read more..

  • Page - 945

    930 STL Algorithms Chapter 32 structure those iterators point into. Iterators exist primarily to isolate algorithms from the data structure on which they operate, and vice versa. 32.3 Policy Arguments Most standard-library algorithms come in two versions: • A ‘‘plain’’ version that performs its action using conventional operations, such as < and == • A version that takes key read more..

  • Page - 946

    Section 32.3 Policy Arguments 931 void f(vector<Predicate>& v1, vector<int>& v2) { auto p1 = nd(v1.begin(),v1.end(),pred); // find element with the value pred auto p2 = nd_if(v2.begin(),v2.end(),pred); // count elements for which pred() returns true } Some operations passed as arguments to an algorithm are meant to modify the element to which they are applied (e.g., some read more..

  • Page - 947

    932 STL Algorithms Chapter 32 traversing a vector, even though the complexity in both cases is linear (O(n)). Complexity measures are not a substitute for common sense and actual time measurements; they are one tool among many to ensure quality code. 32.4 Nonmodifying Sequence Algorithms A nonmodifying algorithm just reads the values of elements of its input sequences; it does not read more..

  • Page - 948

    Section 32.4.3 count() 933 32.4.3 count() count (§iso.25.2.9) x=count(b,e,v) x is the number of elements ∗p in [b:e) such that v== ∗p x=count_if(b,e,v,f) x is the number of elements ∗p in [b:e) such that f( ∗p) For example: void f(const string& s) { auto n_space = count(s.begin(),s.end(),' '); auto n_whitespace = count_if(s.begin(),s.end(),isspace); // ... } The isspace() predicate (§36.2) read more..

  • Page - 949

    934 STL Algorithms Chapter 32 array<int> x = {1,3,4 }; array<int> y = {0,2,3,4,5}; void f() { auto p = nd_ rst_of(x.begin(),x.end(),y.begin(),y.end); // p = &x[1] auto q = nd_ rst_of(p+1,x.end(),y.begin(),y.end()); // q = &x[2] } The iterator p will point to x[1] because 3 is the first element of x with a match in y . Similarly, q will point to x[2] . 32.4.5 equal() read more..

  • Page - 950

    Section 32.4.6 search() 935 32.4.6 search() The search() and search_n() algorithms find one sequence as a subsequence in another: Searching for Sequences (§iso.25.2.13) p=search(b,e ,b2,e2) p points to the first ∗p in [b:e) such that [p:p+(e b) ) equals [b2:e2) p=search(b.e ,b2,e2,f) p points to the first ∗p in [b:e) such that [p:p+(e b) ) equals [b2:e2), using f for element comparison read more..

  • Page - 951

    936 STL Algorithms Chapter 32 Somewhat confusingly, transform() doesn’t necessarily change its input. Instead, it produces an out- put that is a transformation of its input based on a user-supplied operation. The one-input-sequence version of transform() may be defined like this: template<class In, c lass Out, class Op> Out transform(In rst, In last, Out res, Op op) { while ( read more..

  • Page - 952

    Section 32.5.1 copy() 937 void f(const vector<char>& vs, vector<c har>& v) { copy(vs.begin(),vs.end(),v.begin()); // might overwr ite end of v copy(vs.begin(),vs.end(),back_inser ter(v)); // add elements from vs to end of v } The input sequence and the output sequence may overlap. We use copy() when the sequences do not overlap or if the end of the output sequence is in the read more..

  • Page - 953

    938 STL Algorithms Chapter 32 Rather, unique() moves unique elements toward the front (head) of a sequence and returns an itera- tor to the end of the subsequence of unique elements. For example: int main() { string s ="abbcccde"; auto p = unique(s.begin(),s.end()); cout << s << ' ' << p s.begin() << '\n'; } produces abcdecde 5 That is, p points to the second read more..

  • Page - 954

    Section 32.5.3 remove() and replace() 939 replace (§iso.25.3.5) replace(b,e,v,v2) Replace elements ∗p in [b:e) for which ∗p==v with v2 replace_if(b,e,f,v2) Replace elements ∗p in [b:e) for which f( ∗p) with v2 p=replace_copy(b,e ,out,v,v2) Copy [b:e)to[out:p), replacing elements for which ∗p==v with v2 p=replace_copy_if(b,e ,out,f,v2) Copy [b:e)to[out:p), replacing elements for which f( ∗p,v) with read more..

  • Page - 955

    940 STL Algorithms Chapter 32 permutation has the same chances of being chosen. If you want a different distribution or a better random number generator, you can supply one. For a call random_shuf e(b,e,r) , the generator is called with the number of elements in the sequence (or a subsequence) as its argument. For exam- ple, for a call r(e b) the generator must return a read more..

  • Page - 956

    Section 32.5.5 Permutations 941 The next_permutation() takes a sequence [b:e) and transforms it into the next permutation. The next permutation is found by assuming that the set of all permutations is lexicographically sorted. If such a permutation exists, next_permutation() returns true ; otherwise, it transforms the sequence into the smallest permutation, that is, the ascendingly sorted one read more..

  • Page - 957

    942 STL Algorithms Chapter 32 storage, say, to turn a region of memory into objects of well-defined type and state, you use one of the uninitialized_ versions (presented in <memory> ). Uninitialized sequences should only occur at the lowest level of programming, usually inside the implementation of containers. Elements that are targets of uninitialized_ ll() or uninitial- ized_copy() read more..

  • Page - 958

    Section 32.6 Sorting and Searching 943 The sort Family (continued)(§iso.25.4.1) stable_sor t(b,e) Sort [b:e) maintaining order of equal elements stable_sor t(b,e,f) Sort [b:e), using f( ∗p,∗q) as the sorting criterion, maintaining order of equal elements partial_sort(b,m,e) Sort enough of [b:e) to get [b:m) into order; [m:e) need not be sorted partial_sort(b,m,e,f) Sort enough of [b:e) to get read more..

  • Page - 959

    944 STL Algorithms Chapter 32 plain partial_sort(b,m,e) algorithms put the elements in the range [b:m) in order. The par- tial_sort_copy() algorithms produce N elements, where N is the lower of the number of elements in the output sequence and the number of elements in the input sequence. We need to specify both the start and the end of the result sequence because that’s read more..

  • Page - 960

    Section 32.6 Sorting and Searching 945 vector<string> vs = {"Helsinki","Copenhagen","Oslo","Stockholm"}; vector<char ∗> vcs = {"Helsinki","Copenhagen","Oslo","Stockholm"}; void use() { sort(vs); // I have defined a range version of sort() sort(vcs); for (auto& x : vs) cout << x << ' ' cout << '\n'; for (auto& x : read more..

  • Page - 961

    946 STL Algorithms Chapter 32 void f(vector<int>& c) { if (binary_search(c.begin(),c.end(),7)) { // is 7 in c? // ... } // ... } A binary_search() returns a bool indicating whether a value is present. As with nd() , we often also want to know where the elements with that value are in that sequence. However, there can be many elements with a given value in a sequence, read more..

  • Page - 962

    Section 32.6.2 merge() 947 vector<int> v {3,1,4,2}; list<double> lst {0.5,1.5,2,2.5}; // lst is in order sort(v.begin(),v.end()); // put v in order vector<double> v2; merge(v.begin(),v.end(),lst.begin(),lst.end(),back_inser ter(v2)); // merger v and lst into v2 for (double x : v2) cout << x << ", "; For inserters, see §33.2.2. The output is: 0.5, 1, 1.5, 2, 2, 2.5, 3, read more..

  • Page - 963

    948 STL Algorithms Chapter 32 string s1 = "qwertyasdfgzxcvb"; string s2 = "poiuyasdfg/.,mnb"; sort(s1.begin(),s1.end()); // the set algorithms require sorted sequences sort(s2.begin(),s2.end()); string s3(s1.size()+s2.siz e(),' ∗'); // set aside enough space for the largest possible result cout << s3 << '\n'; auto up = set_union(s1.begin(),s1.end(),s2.begin(),s2.end(),s3.begin()); cout read more..

  • Page - 964

    Section 32.6.4 Heaps 949 Think of the end, e , of a heap [b:e) as a pointer, which it decremented by pop_heap() and incre- mented by push_heap() . The largest element is extracted by reading through b (e.g., x= ∗b) and then doing a pop_heap() . A new element is inserted by writing through e (e.g., ∗e=x) and then doing a push_heap() . For example: string s = read more..

  • Page - 965

    950 STL Algorithms Chapter 32 string n1 {"10000"}; string n2 {"999"}; bool b1 = lexicographical_compare(n1.begin(),n1.end(),n2.begin(),n2.end()); // b1 == true n1 = "Zebra"; n2 = "Aardvark"; bool b2 = lexicographical_compare(n1.begin(),n1.end(),n2.begin(),n2.end()); // b2 == false 32.7 Min and Max Value comparisons are useful in many contexts: The min and max Family read more..

  • Page - 966

    Section 32.7 Min and Max 951 ++min(x,y); // the result of min(x,y) is a const int& ++min({x,y}); // error : the result of min({x,y}) is an rvalue (an initializer_list is immutable) The _element functions return iterators and the minmax function returns pair s, so we can write: string s = "Large_Hadron_Collider"; auto p = minmax_element(s.begin(),s.end(), [](char c1,char c2) { read more..

  • Page - 967

    This page intentionally left blank read more..

  • Page - 968

    33 STL Iterators The reason that STL containers and algorithms work so well together is that they know nothing of each other. – Alex Stepanov • Introduction • Iterator Model Iterator Categories; Iterator Traits; Iterator Operations • Iterator Adaptors Reverse Iterators; Insert Iterators; Move Iterator • Range Access Functions • Function Objects • Function Adaptors bind() ; mem_fn() ; read more..

  • Page - 969

    954 STL Iterators Chapter 33 sor t() nd() merge() ... my_algo() your_fct() Iterators vector map list ... my_container your_container 33.1.1 Iterator Model An iterator is akin to a pointer in that it provides operations for indirect access (e.g., ∗ for derefer- encing) and for moving to point to a new element (e.g., ++ for moving to the next element). A sequence is defined by a pair read more..

  • Page - 970

    Section 33.1.1 Iterator Model 955 Algorithms that write to a sequence often are given only an iterator to its first element. In that case, it is the programmer’s responsibility not to write beyond the end of that sequence. For example: template<typename Iter> void forward(Iter p, int n) { while (n>0) ∗p++ = n; } void user() { vector<int> v(10); forward(v.begin(),v.siz e()); read more..

  • Page - 971

    956 STL Iterators Chapter 33 Iterator ∗, ++ Input Iterator == , != , single read, > Output Iterator single write Forward Iterator repeated read and write Bidirectional Iterator Random-access Iterator [] , + , += , , = , < , <= , > , >= The iterator categories are concepts (§24.3) rather than classes, so this hierarchy is not a class hier- archy implemented using derivation. If read more..

  • Page - 972

    Section 33.1.3 Iterator Traits 957 The iterator tags are types used to select among algorithms based on the type of an iterator. For example, a random-access iterator can go directly to an element: template<typename Iter> void advance_helper(Iter p, int n, random_access_iterator_tag) { p+=n; } On the other hand, a forward iterator must get to the n th element by moving one step read more..

  • Page - 973

    958 STL Iterators Chapter 33 We cannot in general say: template<typename Iter> typename Iter::value_type read(Iter p, int n) // not general { // ... do some checking ... return p[n]; { This is an error waiting to happen. Calling this read() with a pointer argument would be an error. The compiler would catch it, but the error messages might be voluminous and obscure. Instead, read more..

  • Page - 974

    Section 33.1.3 Iterator Traits 959 template<typename Cat, typename T , typename Dist = ptrdiff_t, typename Ptr = T ∗, typename Ref = T&> struct iterator { using value_type = T; using difference_type = Dist ; // type used by distance() using pointer = Ptr; // pointer type using reference = Ref; // reference type using iterator_category = Cat; // categor y (tag) }; 33.1.4 read more..

  • Page - 975

    960 STL Iterators Chapter 33 Iterator Operations (§iso.24.4.4) advance(p) Like p+=n ; p must be at least an input iterator x=distance(p,q) Like x=q p ; p must be at least an input iterator q=next(p,n) Like q=p+n ; p must be at least a forward iterator q=next(p) q=next(p,1) q=prev(p,n) Like q=p n ; p must be at least a bidirectional iterator q=prev(p) q=prev(p,1) In each case, if p read more..

  • Page - 976

    Section 33.2.1 Reverse Iterator 961 rbegin() rend() C B A The definition of reverse_iterator looks something like this: template<typename Iter> class reverse_iterator : public iterator<Iterator_category<Iter>, Value_type<Iter>, Difference_type<Iter>, Pointer<Iter>, Reference<Iter>> { public: using iterator_type = Iter; reverse_iterator(): current{} { } explicit reverse_iterator(Iter p): read more..

  • Page - 977

    962 STL Iterators Chapter 33 void f(vector<int>& v, list<char>& lst) { v.rbegin()[3] = 7; // OK: random-access iterator lst.rbegin()[3] = '4'; // error : bidirectional iterator doesn’t support [] ∗(next(lst.rbegin(),3)) = '4'; // OK! } I use next() to move the iterator because (like [] ) + wouldn’t work for a bidirectional iterator, such as list<char>::iterator . read more..

  • Page - 978

    Section 33.2.2 Insert Iterators 963 33.2.2 Insert Iterators Producing output through an iterator into a container implies that elements following the one pointed to by the iterator can be overwritten. This implies the possibility of overflow and conse- quent memory corruption. For example: void f(vector<int>& vi) { ll_n(vi.begin(),200,7); // assign 7 to vi[0]..[199] } If vi has fewer read more..

  • Page - 979

    964 STL Iterators Chapter 33 insert_iterator<C> Operations (continued) (§iso.24.5.2) ++p Make p point to the next element; the value is p ’s new value p++ Make p point to the next element; the value is p ’s old value ∗p=x Insert x before p ∗p++=x Insert x before p , then increment p The front_inser t_iterator and back_inser t_iterator differ in that their constructors read more..

  • Page - 980

    Section 33.3 Range Access Functions 965 template<typename C> auto begin(C& c) > dec ltype(c.begin()); template<typename C> auto begin(const C& c) > dec ltype(c.begin()); template<typename C> auto end(C& c) > dec ltype(c.end()); template<typename C> auto end(const C& c) > dec ltype(c.end()); template<typename T , siz e_t N> // for built-in arrays auto begin(T (&array)[N]) read more..

  • Page - 981

    966 STL Iterators Chapter 33 Here, I assume that passing the address of the first element is a way to create an iterator to the first element of My_container and that My_container has a size() . 33.4 Function Objects Many of the standard algorithms take function objects (or functions) as arguments to control the way they work. Common uses are comparison criteria, predicates read more..

  • Page - 982

    Section 33.5 Function Adaptors 967 33.5 Function Adaptors A function adaptor takes a function as argument and returns a function object that can be used to invoke the original function. Adaptors (§iso.20.8.9, §iso.20.8.10, §iso.20.8.8) g=bind(f,args) g(args2) is equivalent to f(args3) where args3 is obtained by replacing placeholders in args with arguments from args2 for the use of read more..

  • Page - 983

    968 STL Iterators Chapter 33 To bind arguments for an overloaded function, we have to explicitly state which version of the function we want to bind: int pow(int,int); double pow(double ,double); // pow() is overloaded auto pow2 = bind(pow,_1,2); // error : which pow()? auto pow2 = bind((double( ∗)(double ,double))pow,_1,2); // OK (but ugly) Note that bind() takes ordinary read more..

  • Page - 984

    Section 33.5.2 mem_fn() 969 33.5.2 mem_fn() The function adaptor mem_fn(mf) produces a function object that can be called as a nonmember function. For example: void user(Shape ∗ p) { p >draw(); auto draw = mem_fn(&Shape::draw); draw(p); } The major use of mem_fn() is when an algorithm requires an operation to be called as a nonmember function. For example: void draw_all(vector<Shape read more..

  • Page - 985

    970 STL Iterators Chapter 33 function<R(Argtypes...)> (continued)(§iso.20.8.11.2) f.swap(f2) Swap the contents of f and f2 ; f and f2 must be of the same function type; noexcept f.assign(f2,a) f gets a copy of f2 and the allocator a bool b {f}; conversion of f to bool ; b is true if f is nonempty; explicit; noexcept r=f(args) Invoke the contained function with args ; the argument read more..

  • Page - 986

    Section 33.5.3 function 971 void t1() { f = round; cout << f(7.6) << '\n'; // call through f to the function round f = Round(Round_style::truncate); cout << f(7.6) << '\n'; // call the function object Round_style style = Round_style::round; f = [style] (double x){ return (style==Round_style::round) ? x+0.5 : x; }; cout << f(7.6) << '\n'; // call the lambda read more..

  • Page - 987

    972 STL Iterators Chapter 33 [17] A mem_fn() or a lambda can be used to convert the p >f(a) calling convention into f(p,a) ; §33.5.2. [18] Use function when you need a variable that can hold a variety of callable objects; §33.5.3. read more..

  • Page - 988

    34 Memory and Resources Anyone can have an idea; it´s what you do with the idea that´s the important thing. – Terry Pratchett • Introduction • ‘‘Almost Containers’’ array ; bitset ; vector<bool> ; Tuples • Resource Management Pointers unique_ptr ; shared_ptr ; weak_ptr • Allocators The Default Allocator; Allocator Traits; Pointer Traits; Scoped Allocators • The Garbage Collection Interface read more..

  • Page - 989

    974 Memory and Resources Chapter 34 ‘‘almost containers’’ (§31.4), b ut that is not quite fair: they hold elements, so they are containers, but each has restrictions or added facilities that make them awkward in the context of the STL. Describing them separately also simplifies the description of the STL. ‘‘ Almost Containers’’ T[N] Built-in array: a fixed-size read more..

  • Page - 990

    Section 34.2.1 array 975 template<typename T , siz e_t N> // an array of N Ts (§iso.23.3.2) struct array { /* types and operations like vector’s (§31.4), except operations that change the container size, constructors, and assign() functions */ void ll(const T& v);/ / assign N copies of v void swap(array&) noexcept(noexcept(swap(declval<T&>(), declval<T&>()))); T read more..

  • Page - 991

    976 Memory and Resources Chapter 34 There is no constructor for array that copies an argument value (as there is for vector ; §31.3.2). Instead, a ll() operation is provided: void f() { array<int,8> aa; // uninitialized, so far aa. ll(99); // assign eight copies of 99 // ... } Because an array doesn’t follow the ‘‘handle to elements’’ model, swap() has to actually swap read more..

  • Page - 992

    Section 34.2.1 array 977 The ‘‘disaster’’ comment assumes that sizeof(Shape)<sizeof(Circle) , so that subscripting a Circle[] through a Shape ∗ gives a wrong offset (§27.2.1, §17.5.1.4). All standard containers provide this advantage over built-in arrays. An array can be seen as a tuple (§34.2.4) where all elements are of the same type. The standard library provides support for that view. read more..

  • Page - 993

    978 Memory and Resources Chapter 34 It is not possible to address a single bit directly using a built-in pointer (§7.2). Consequently, bitset provides a reference-to-bit (proxy) type. This is actually a generally useful technique for addressing objects for which a built-in pointer for some reason is unsuitable: template<size_t N> class bitset { public: class reference { // reference read more..

  • Page - 994

    Section 34.2.2.1 Constructors 979 bitset<N> Constructors (continued) (§iso.20.5.1) bitset bs {p,n,z,o}; n bits [p:p+n); p is a C-style string of type C ∗; z is the character of type C used for zero; o is the character of type C used for one; explicit bitset bs {p,n,z}; bitset bs {p,n,z,C{’0’}}; bitset bs {p,n}; bitset bs {p,n,C{’1’},C{’0’}}; bitset bs {p}; bitset bs read more..

  • Page - 995

    980 Memory and Resources Chapter 34 bitset<N> Operations (continued) (§iso.20.5) bs<<=n Logical left shift (fill with zeros) bs>>=n Logical right shift (fill with zeros) bs.set() Set every bit of bs to 1 bs.set(i,v) bs[i]=v bs.reset() Set every bit of bs to 0 bs.reset(i) b[i]=0 ; bs. ip() bs[i]=˜bs[i] for every bit in bs bs. ip(i) bs[i]=˜bs[i] bs2=˜bs Make complement set: read more..

  • Page - 996

    Section 34.2.2.2 bitset Operations 981 More bitset<N> Operations (continued) (§iso.20.5) C , Tr , and A have defaults for basic_string<C,Tr,A> n=bs.count() n is the number of bits with value 1 in bs n=bs.size() n is the number of bits in bs bs==bs2 Do bs and b2 have the same value? bs!=bs2 !(bs==bs2) bs.all() Do all bits in bs have the value 1 ? bs.any() Does any bit read more..

  • Page - 997

    982 Memory and Resources Chapter 34 template<typename A> class vector<bool,A> { // specialization of vector<T,A> (§31.4) public: using const_reference = bool; using value_type = bool; // like vector<T,A> class reference { // suppor t zero-based subscripting in [0:v.size()) friend class vector; reference() noexcept; public: ˜reference(); operator bool() const noexcept; reference& read more..

  • Page - 998

    Section 34.2.4.1 pair 983 34.2.4.1 pair In <utility> , the standard library provides class pair for manipulating pairs of values: template<typename T , typename U> struct pair { using rst_type = T; // the type of the first element using second_type = U; // the type of the second element T rst; // first element U second; // second element // ... }; pair<T,U> read more..

  • Page - 999

    984 Memory and Resources Chapter 34 using Tup = tuple<string,int>; Tup t1 {"Columbia",11}; // U.S. News 2012 Tup t2 {"Cambridg e",2}; pair<Tub,Tub> p1 {t1,t2}; // pair of tuples pair<Univ,Univ> p2 {piece wise_construct,t1,t2}; // pair of Univs That is, p1.second is t2 , that is, {"Cambridge",2} . To contrast, p2.second is Univ{t2} , that is, {"Cam- read more..

  • Page - 1000

    Section 34.2.4.2 tuple 985 tuple<Types...> Members (continued) (§iso.20.4.2) tuple t {allocator_arg_t,a,args}; Construct from args using the allocator a tuple t {allocator_arg_t,a,t2}; Construct from tuple t2 , using the allocator a tuple t {allocator_arg_t,a,p}; Construct from pair p , using the allocator a t.˜tuple() Destructor: destroy each element t=t2 Copy assignment of tuple s t=move(t2) Move read more..

  • Page - 1001

    986 Memory and Resources Chapter 34 tuple<Types...> Helpers (continued) (§iso.20.4.2.4, §iso.20.4.2.9) t=tuple_cat(args) Concatenate tuple s: args is one or more tuple s; t has the members of the tuple sin args in order tuple_size<T>::value The number of elements of the tuple T tuple_elements<N,T>::type The type of the N th element of the tuple T get<N>(t) A reference to the read more..

  • Page - 1002

    Section 34.3.1 unique_ptr 987 34.3.1 unique_ptr The unique_ptr (defined in <memory> ) provides a semantics of strict ownership: •A unique_ptr owns the object to which it holds a pointer. That is, it is the unique_ptr ’s obli- gation to destroy the object pointed to (if any) by its contained pointer. •A unique_ptr cannot be copied (has no copy constructor or copy read more..

  • Page - 1003

    988 Memory and Resources Chapter 34 unique_ptr<T,D> (§iso.20.7.1.2) cp is the contained pointer unique_ptr up {} Default constructor: cp=nullptr ; constexpr; noexcept unique_ptr up {p} cp=p ; use the default deleter; explicit; noexcept unique_ptr up {p,del} cp=p ; del is the deleter; noexcept unique_ptr up {up2} Move constructor: cp.p=up2.p; up2.p=nullptr ; noexcept up.˜unique_ptr() Destructor: if read more..

  • Page - 1004

    Section 34.3.1 unique_ptr 989 template<typename T , typename D> class unique_ptr<T[],D> { // specialization for arrays (§iso.20.7.1.3) // the default D=default_delete<T> comes from the general unique_ptr public: // ... like the unique_ptr for individual objects, but with [] instead of * and -> ... }; To avoid slicing (§17.5.1.4), a Derived[] is not accepted as an argument to a read more..

  • Page - 1005

    990 Memory and Resources Chapter 34 significant. On the other hand, access to the contained pointer involves an extra indirection in f2() compared to f() . This, too, is unlikely to be significant in most programs, so the choice between the styles of f() and f2() has to be made on reasoning about code quality. Here is a simple example of a deleter used to provide read more..

  • Page - 1006

    Section 34.3.2 shared_ptr 991 struct Node { vector<Node ∗> edg es; // ... }; Given that, answering questions such as ‘‘How many nodes points to this node?’’ is very hard and requires much added ‘‘housekeeping’’ code. We could plug in a garbage collector (§34.5), b ut that could have neg ative performance implications if the graph was only a small part of read more..

  • Page - 1007

    992 Memory and Resources Chapter 34 • Prefer unique_ptr to shared_ptr . • Prefer ordinary scoped objects to objects on the heap owned by a unique_ptr . The shared_ptr provides a fairly conventional set of operations: shared_ptr<T> Operations (§iso.20.7.2.2) cp is the contained pointer; uc is the use count shared_ptr sp {} Default constructor: cp=nullptr; uc=0 ; noexcept shared_ptr sp read more..

  • Page - 1008

    Section 34.3.2 shared_ptr 993 shared_ptr<T> Helpers (continued) (§iso.20.7.2.2.6, §iso.20.7.2.2.7) sp==sp2 sp.cp==sp2.cp ; sp or sp2 may be the nullptr sp<sp2 less<T ∗>(sp.cp,sp2.cp); sp or sp2 may be the nullptr sp!=sp2 !(sp=sp2) sp>sp2 sp2<sp sp<=sp2 !(sp>sp2) sp>=sp2 !(sp<sp2) swap(sp,sp2) sp.swap(sp2) sp2=static_pointer_cast(sp) static_cast for shared pointers: read more..

  • Page - 1009

    994 Memory and Resources Chapter 34 sp1 : sp2 : wp : use count deleter weak use count Object The ‘‘weak use count’’ is needed to keep the use count structure alive because there may be weak_ptr s after the last shared_ptr for an object (and the object) is destroyed. template<typename T> class weak_ptr { public: using element_type = T; // ... }; A weak_ptr has to be read more..

  • Page - 1010

    Section 34.3.3 weak_ptr 995 destroyed while another asteroid is looking at it (e.g., to calculate the effect of a collision). And obviously, an asteroid destructor must be called to release resources (such as a connection to the graphics system). What we need is a list of asteroids that might still be intact and a way of ‘‘grab- bing onto one’’ for a while. A read more..

  • Page - 1011

    996 Memory and Resources Chapter 34 template<typename T> struct Simple_alloc { // use new[] and delete[] to allocate and deallocate bytes using value_type = T; Simple_alloc() {} T ∗ allocate(size_t n) { return reinterpret_cast<T ∗>(new char[n ∗sizeof(T)]); } void deallocate(T ∗ p, size_t n) { delete[] reinterpret_cast<char ∗>(p); } // ... }; Simple_alloc happens to be the read more..

  • Page - 1012

    Section 34.4 Allocators 997 template<typename T> using Arena_vec = std::vector<T,My_alloc<T>>; template<typename T> using Simple_vec = std::vector<T,Simple_alloc<T>>; My_alloc<int> Alloc2 {my_arena2}; // named allocator object Arena_vec<complex<double>> vcd {{{1,2}, {3,4}}, Alloc2}; // explicit allocator Simple_vec<string> vs {"Sam Vimes", "Fred Colon", "Nobby read more..

  • Page - 1013

    998 Memory and Resources Chapter 34 template<typename U> void destroy(U ∗ p); // p->˜U() }; The curious rebind template is an archaic alias. It should have been: template<typename U> using other = allocator<U>; However, allocator was defined before such aliases were supported by C++. It is provided to allow an allocator to allocate objects of arbitrary type. Consider: read more..

  • Page - 1014

    Section 34.4.2 Allocator Traits 999 template<typename A> // §iso.20.6.8 struct allocator_traits { using allocator_type = A; using value_type = A::value_type; using pointer = value_type; // trick using const_pointer = Pointer_traits<pointer>::rebind<const value_type>; // trick using void_pointer = Pointer_traits<pointer>::rebind<void>; // trick using const_void_pointer = read more..

  • Page - 1015

    1000 Memory and Resources Chapter 34 template<typename U> using rebind = T ∗;// trick static pointer pointer_to(a); // trick }; template<typename T> struct pointer_traits<T ∗>{ using pointer = T ∗; using element_type = T; using difference_type = ptrdiff_t; template<typename U> using rebind = U ∗; static pointer pointer_to(x) noexcept { return addressof(x); } }; The read more..

  • Page - 1016

    Section 34.4.4 Scoped Allocators 1001 using value_type = typename Tr::value_type; using size_type = typename Tr::siz e_type; using difference_type = typename Tr::difference_type; using pointer = typename Tr::pointer; using const_pointer = typename Tr::const_pointer; using void_pointer = typename Tr::void_pointer; using const_void_pointer = typename Tr::const_void_pointer; using propagate_on_container_copy_assignment = read more..

  • Page - 1017

    1002 Memory and Resources Chapter 34 scoped_allocator_adaptor<OuterA,InnerA> (continued) (Abbreviated, §iso.20.12.1) p=a.allocate(n,hint) Acquire space for n objects of value_type hint is an implementation-dependent help for the allocator; often, hint is a pointer to an object to which we would like ∗p to be near a.deallocate(p,n) Free the space for n objects of value_type pointed to by p read more..

  • Page - 1018

    Section 34.5 The Garbage Collection Interface 1003 From this basic philosophy it follows that garbage collection is optional in C++. A garbage col- lector will not be invoked unless explicitly installed and activated. A garbage collector is not even a required part of a standard C++ implementation, but good free and commercial collectors are available. C++ provides a definition of read more..

  • Page - 1019

    1004 Memory and Resources Chapter 34 Using that trick, no undisguised pointers to links are stored. Don’t use such tricks in a program you want to be considered well behaved and comprehensible to ordinary mortals – even if you don’t plan to use a garbage collector. There are many more and ev en nastier tricks, such as scattering the bits of a pointer around in read more..

  • Page - 1020

    Section 34.6 Uninitialized Memory 1005 34.6 Uninitialized Memory Most of the time, it is best to avoid uninitialized memory. Doing so simplifies programming and eliminates many kinds of errors. However, in relatively rare cases, such as when writing memory allocators, implementing containers, and dealing directly with hardware, direct use of uninitialized memory, also known as raw memory, read more..

  • Page - 1021

    1006 Memory and Resources Chapter 34 template<typename Out, typename T> class raw_storage_iterator : public iterator<output_iterator_tag,void,void,void,void> { Out p; public: explicit raw_storage_iterator(Out pp) : p{pp} { } raw_storage_iterator& operator ∗() { return ∗this; } raw_storage_iterator& operator=(const T& v al) { new(& ∗p) T{val}; // place val in *p (§11.2.4) return ∗this; } read more..

  • Page - 1022

    Section 34.7 Advice 1007 34.7 Advice [1] Use array where you need a sequence with a constexpr size; §34.2.1. [2] Prefer array over built-in arrays; §34.2.1. [3] Use bitset if you need N bits and N is not necessarily the number of bits in a built-in integer type; §34.2.2. [4] Avoid vector<bool> ; §34.2.3. [5] When using pair , consider make_pair() for type deduction; read more..

  • Page - 1023

    This page intentionally left blank read more..

  • Page - 1024

    35 Utilities The time you enjoy wasting is not wasted time. – Bertrand Russell • Introduction • Time duration ; time_point ; Clocks; Time Traits • Compile-Time Rational Arithmetic • Type Functions Type Traits; Type Generators • Minor Utilities move() and forward() ; swap() ; Relational Operators; Comparing and Hashing type_info • Advice 35.1 Introduction The standard library provides many read more..

  • Page - 1025

    1010 Utilities Chapter 35 If you want to know the current time_point , you can call now() for one of three clocks: sys- tem_clock , steady_clock , high_resolution_clock . For example: steady_clock::time_point t = steady_clock::now(); // ... do something ... steady_clock::duration d = steady_clock::now() t; // something took d time units A clock returns a time_point , and a duration is the read more..

  • Page - 1026

    Section 35.2.1 duration 1011 duration<long long,milli> d1 {7}; // 7 milliseconds duration<double ,pico> d2 {3.33}; // 3.33 picoseconds duration<int,ratio<1,1>> d3 {}; // 0 seconds A duration ’s period holds the number of clock ticks of the period . cout << d1.count() << '\n'; // 7 cout << d2.count() << '\n'; // 3.33 cout << d3.count() << '\n'; // 0 Naturally, the read more..

  • Page - 1027

    1012 Utilities Chapter 35 duration<long long,milli> d1 {7}; // 7 milliseconds d1 += 5; // error duration<int,ratio<1,1>> d2 {7}; // 7 seconds d2 = 5; // error d2 += 5; // error What would 5 mean here? 5 seconds? 5 milliseconds? Something else? If you know what you mean, be explicit about it. For example: d1 += duration<long long,milli>{5}; // OK: milliseconds d3 += read more..

  • Page - 1028

    Section 35.2.1 duration 1013 using nanoseconds = duration<si64,nano>; using microseconds = duration<si55,micro>; using milliseconds = duration<si45,milli>; using seconds = duration<si35>; using minutes = duration<si29,ratio<60>>; using hours = duration<si23,ratio<3600>>; Here, siN means ‘‘an implementation-defined signed inte ger type of at least N bits.’’ The read more..

  • Page - 1029

    1014 Utilities Chapter 35 time_point<Clock,Duration> (§iso.20.11.6) time_point tp {}; Default constructor: start of epoch: duration::zero() time_point tp {d}; Constructor: time point d of epoch: time_point{}+d ; explicit time_point tp {tp2}; Constructor: tp refers to the same point in time as tp2 ; tp2 ’s duration type must be implicitly convertible to tp ’s d=tp.time_since_epoch() d is tp read more..

  • Page - 1030

    Section 35.2.2 time_point 1015 void test2() { auto tp = steady_clock::now(); auto d1 = time_point_cast<hours>(tp).time_since_epoch().count()/24; // days since start of epoch using days = duration<long,ratio<24 ∗60∗60,1>>; // a day’s duration auto d2 = time_point_cast<days>(tp).time_since_epoch().count(); // days since start of epoch if (d1!=d2) cout << "Impossible!\n"; } read more..

  • Page - 1031

    1016 Utilities Chapter 35 A system provides three named clocks: Clock Types (§iso.20.11.7) system_clock The system’s real-time clock; the system’s clock may be reset (jump forward or backward) to match external clocks steady_clock A clock where time moves steadily forward; that is, time does not go backward and the time between clock ticks is constant high_resolution_clock A clock with read more..

  • Page - 1032

    Section 35.2.4 Time Traits 1017 This makes type an alias for the duration with the largest possible tick period so that both duration arguments will convert to it without requiring a division operation. This implies that com- mon_type<R1,P1,R2,P2>::type can hold any value from duration<R1,R2> and duration<R2,P2> without truncation error. Howev er, floating-point duration s may read more..

  • Page - 1033

    1018 Utilities Chapter 35 Obviously, this is not a convenient way of expressing numbers and arithmetic. In <chrono> ,wefind the conventional notation (e.g., + and ∗) for rational arithmetic for time (§35.2). Similarly, to help express unit values, the standard library provides common SI magnitude names: using yocto = ratio<1,1000000000000000000000000>; // conditionally supported read more..

  • Page - 1034

    Section 35.4.1 Type Traits 1019 Primary Type Predicates (continued) (§iso.20.9.4.1) is_lvalue_reference<X> Is X an lvalue reference? is_rvalue_reference<X> Is X an rvalue reference? is_member_object_pointer<X> Is X a pointer to a non-static data member? is_member_function_pointer<X> Is X a pointer to a non-static member function? is_enum<X> Is X an enum (either plain of class enum read more..

  • Page - 1035

    1020 Utilities Chapter 35 Like the primary type predicates, type property predicates provide tests for fundamental aspects of a type: Type property predicates (§iso.20.9.4.3) is_const<X> Is X a const ? is_volatile<X> Is X a volatile (§41.4)? is_trivial<X> Is X a trivial type (§8.2.6)? is_trivially_copyable<X> Can X be copied, moved, and destroyed as a simple collection of bits read more..

  • Page - 1036

    Section 35.4.1 Type Traits 1021 For a class to be empty, it can have no virtual functions, no virtual bases, and no base classes for which !is_empty<Base>::value . The type property predicates don’t do access checking depending on where they are used. Instead, they consistently give the result you would expect for a use outside members and friends. For example: class X read more..

  • Page - 1037

    1022 Utilities Chapter 35 Type Property Predicates (continued) (§iso.20.9.4.3) is_nothrow_constructible<X,args> Can X be constructed from args using only noexcept operations? is_nothrow_default_constructible<X> is_nothrow_copy_constructible<X> is_nothrow_move_constructible<X> is_nothrow_assignable<X,Y> is_nothrow_copy_assignable<X> is_nothrow_move_assignable<X> is_nothrow_destructible<X> read more..

  • Page - 1038

    Section 35.4.2 Type Generators 1023 35.4.2 Type Generators In <type_traits> , the standard library provides type functions for producing a type given other types as arguments. const and volatile Modification (§iso.20.9.7.1) remove_const<X> Like X , but with any top-level const removed remove_volatile<X> Like X , but with any top-level volatile removed remove_cv<X> Like X , but read more..

  • Page - 1039

    1024 Utilities Chapter 35 template<typename T> void f(T v) { Remove_reference<T> x = v; // copyofv Ty=v; // maybe copy of v; maybe a reference to x ++x; // increment local var iable ++y; // ... } Here, x really is a copy of v , but if T is a reference type, y is a reference to v : void user() { int val = 7; f(val); // call f<int&>(): the ++y in f() will read more..

  • Page - 1040

    Section 35.4.2 Type Generators 1025 template<typename T> void f(T x) { Add_pointer<T> p = new Remove_reference<T>{}; T ∗ p = new T{}; // would not wor k if T is a reference // ... } When dealing with memory at the lowest levels of a system, we must sometimes consider align- ment (§6.2.9): Alignments (§iso.20.9.7.6) aligned_storage<n,a> A POD type with size of at read more..

  • Page - 1041

    1026 Utilities Chapter 35 template<typename ...T> struct common_type; template<typename T> struct common_type<T> { using type = T; }; The common type of two types is what the rules for ?: (§11.1.3) give us: template<typename T , typename U> struct common_type<T, U> { using type = decltype(true ? declval<T>() : decl val<U>()); }; The declval<T>() type function read more..

  • Page - 1042

    Section 35.4.2 Type Generators 1027 Note that Result_of can distinguish between the two versions of Fct::operator()() . Curiously enough, the same does not apply to nonmember functions. For example: int f(); // function string f(int); Result_of<decltype(&f)()> r1 = 7; // error : no overload resolution for pointer to function Unfortunately, we don’t do overload resolution for pointers to read more..

  • Page - 1043

    1028 Utilities Chapter 35 35.5 Minor Utilities These utilities are minor in size, but not in importance. They don’t fit into a larger grouping. 35.5.1 move() and forward() In <utility> , we find some of the most useful small functions: Other Transformations (§iso.20.9.7.6) x2=forward(x) x2 is an rvalue; x may not be an lvalue; noexcept x2=move(x) x2 is an rvalue; noexcept read more..

  • Page - 1044

    Section 35.5.1 move() and forward() 1029 The archetypical use of forward() is for ‘‘perfect forw arding’’ of an argument from one function to another (§23.5.2.1, §28.6.3). The standard-library make_shared<T>(x) (§34.3.2) is a good e xam- ple. Use move() when the intent is to ‘‘steal the representation’’ of an object with a move operation, and use forward() for forwarding. Thus, read more..

  • Page - 1045

    1030 Utilities Chapter 35 For example: struct Val { double d; bool operator==(Val v) const { return v.d==d; } }; void my_algo(vector<Val>& vv) { using namespace std::rel_ops; for (int i=0; i<ww.siz e(); ++i) if (0>ww[i]) ww[i]=abs(ww[i]); // OK: > from rel_ops } It can be hard to use rel_ops without polluting a namespace. In particular: namespace Mine { struct Val { double d; read more..

  • Page - 1046

    Section 35.5.4 Comparing and Hashing type_info 1031 unordered_map<type_index,type_info ∗> types; // ... types[type_index{something}] = &typeid(something); 35.6 Advice [1] Use <chrono> facilities, such as steady_clock , duration , and time_point for timing; §35.2. [2] Prefer <clock> facilities over <ctime> facilities; §35.2. [3] Use duration_cast to get durations in known units of read more..

  • Page - 1047

    This page intentionally left blank read more..

  • Page - 1048

    36 Strings Prefer the standard to the offbeat. – Strunk & White • Introduction • Character Classification Classification Functions; Character Traits • Strings string vs. C-Style Strings; Constructors; Fundamental Operations; String I/O; Numeric Con- versions; STL-like Operations; The nd Family; Substrings • Advice 36.1 Introduction The standard library offers character classification operations read more..

  • Page - 1049

    1034 Strings Chapter 36 36.2.1 Classification Functions In <cctype> , the standard library provides functions to classify the characters from the basic execu- tion character set: Character Classification isspace(c) Is c whitespace (space '' , horizontal tab '\t' , newline '\n' , vertical tab '\v' , form feed '\f' , carriage return '\r' )? isalpha(c) Is c a letter ('a'..'z', 'A' ..'Z')? read more..

  • Page - 1050

    Section 36.2.2 Character Traits 1035 36.2.2 Character Traits As shown in §23.2, a string template can, in principle, use any type with proper copy operations as its character type. However, efficiency can be improved and implementations can be simplified for types that don’t hav e user-defined copy operations. Consequently, the standard string requires that a type used as its character read more..

  • Page - 1051

    1036 Strings Chapter 36 char_traits<C> static Members (§iso.21.2) n=length(p) n is the number of characters in [p:q) where ∗q is the first element so that eq(q,charT{}) p2= nd(p,n,c) p points to the first occurrence of c in [p:p+n)or nullptr i=eof() i is the int_type value representing end-of-file i=not_eof(i) i if !eq_int_type(i,eof()) ; otherwise i can be any value not equal to read more..

  • Page - 1052

    Section 36.3 Strings 1037 Specializations are offered for a few standard character types: using string = basic_string<char>; using u16string = basic_string<char16_t>; using u32string = basic_string<char32_t>; using wstring = basic_string<wchar_t>; All these strings provide a host of operations. Like containers (Chapter 31), basic_string is not meant to be used as a base class read more..

  • Page - 1053

    1038 Strings Chapter 36 Did I get that right? I hope so. At least it gav e the output I expected. Like most experienced C programmers, I got the C version correct (I hope) the first time, but there are a lot of details to get right. However, experience (i.e., error logs) shows that this is not always the case. Often, such simple programming tasks are given to read more..

  • Page - 1054

    Section 36.3.2 Constructors 1039 36.3.2 Constructors A basic_string offers a bewildering variety of constructors: basic_string<C,Tr,A> Constructors (§iso.21.4.2) x can be a basic_string , a C-style string, or an initializer_list<char_type> basic_string s {a}; s is an empty string with allocator a ; explicit basic_string s {}; Default constructor: basic_string s {A{}}; basic_string s {x,a}; s read more..

  • Page - 1055

    1040 Strings Chapter 36 If you try to construct a string with more characters than your implementation can handle, the constructor throws std::length_error . For example: string s9 {string::npos,'x'}; // throw length_error The value string::npos represents a position beyond a string ’s length and is generally used to mean ‘‘the end of the string .’’ For example: string ss read more..

  • Page - 1056

    Section 36.3.3 Fundamental Operations 1041 An example: void ll(istream& in, string& s, int max) // use s as target for low-level input (simplified) { s.reserve(max); // make sure there is enough allocated space in.read(&s[0],max); const int n = in.gcount(); // number of characters read s.resize(n); s.shrink_to_ t(); // discard excess capacity } Here, I ‘‘forgot’’ to make use of read more..

  • Page - 1057

    1042 Strings Chapter 36 36.3.4 String I/O A basic_string can be written using << (§38.4.2) and read into using >> (§38.4.1): basic_string<C,Tr,A> I/O Operations (§iso.21.4.8.9) in>>s Read a whitespace-separated word into s from in out<<s Write s to out getline(in,s,d) Read characters from in into s until the character d is encountered; d is removed from in but not appended read more..

  • Page - 1058

    Section 36.3.5 Numeric Conversions 1043 Numeric Conversions (continued) (§iso.21.5) s can be a string or a wstring x=stof(s,p) String to oat x=stod(s,p) String to double x=stold(s,p) String to long double s=to_string(x) s is a string representation of x ; x must be an integer or floating-point value ws=to_wstring(x) s is a wstring representation of x ; x must be an integer or floating-point read more..

  • Page - 1059

    1044 Strings Chapter 36 The sto ∗ functions encode their target type in their names. This makes them unsuitable for generic code where the target can be a template parameter. In such cases, consider to<X> (§25.2.5.1). 36.3.6 STL-like Operations The basic_string provides the usual set of iterators: basic_string<C,Tr,A> String Iterators (§iso.21.4.3) All operations are noexcept read more..

  • Page - 1060

    Section 36.3.6 STL-like Operations 1045 basic_string<C,Tr,A> Insertion and Deletion (§iso.21.4.6.2, §iso.21.4.6.4, §iso.21.4.6.5) All operations return the string to which they are applied s.append(x) Append x at the end of s ; x can be a character, a string , a C-style string, or an initializer_list<char_type> s.append(b,e) Append [b:e) at the end of s s.append(s2,pos,n) Append read more..

  • Page - 1061

    1046 Strings Chapter 36 basic_string<C,Tr,A> Replace (continued) (§iso.21.4.6.6) All operations return the string to which they are applied s.replace(b,e,x) Replace [b:e) with x ; x is a string , a C-style string, or an initializer_list<char_type> s.replace(b,e,p,n) Replace [b:e) with [p:p+n) s.replace(b,e,n,c) Replace [b:e) with n copies of the character c s.replace(b,e,b2,e2) Replace [b:e) read more..

  • Page - 1062

    Section 36.3.7 The nd Family 1047 For example: void f() { string s {"accdcde"}; auto i1 = s. nd("cd"); // i1==2 s[2]=='c' && s[3]=='d' auto i2 = s.r nd("cd"); // i2==4 s[4]=='c' && s[5]=='d' } The nd_ ∗_of() functions differ from nd() and r nd() by looking for a single character, rather than a whole sequence of characters: basic_string<C,Tr,A> read more..

  • Page - 1063

    1048 Strings Chapter 36 36.3.8 Substrings A basic_string offers a low-level notion of substring: basic_string<C,Tr,A> Substrings (§iso.21.4.7.8) s2=s.substr(pos,n) s2=basic_string(&s[pos],m) where m=min(s.size() n,n) s2=s.substr(pos) s2=s.substr(pos,string::npos) s2=s.substr() s2=s.substr(0,string::npos) Note that substr() creates a new string: void user() { string s = "Mary had a little lamb"; string read more..

  • Page - 1064

    Section 36.4 Advice 1049 36.4 Advice [1] Use character classifications rather than handcrafted checks on character ranges; §36.2.1. [2] If you implement string-like abstractions, use character_traits to implement operations on characters; §36.2.2. [3] A basic_string can be used to make strings of characters on any type; §36.3. [4] Use string s as variables and members rather than as read more..

  • Page - 1065

    This page intentionally left blank read more..

  • Page - 1066

    37 Regular Expressions If the code and the comments disagree, then both are probably wrong. – Norm Schryer • Regular Expressions Regular Expression Notation • regex Match Results; Formatting • Regular Expression Functions regex_match() ; regex_search() ; regex_replace() • Regular Expression Iterators regex_iterator ; regex_token_iterator • regex_traits • Advice 37.1 Regular Expressions In read more..

  • Page - 1067

    1052 Regular Expressions Chapter 37 The result of a regex_search() is a collection of matches, typically represented as an smatch : void use() { ifstream in(" le.txt"); // input file if (!in) cerr << "no le\n"; regex pat {R"(\w{2}\s ∗\d{5}( \d{4})?)"}; // U.S. postal code pattern int lineno = 0; for (string line; getline(in,line);) { ++lineno; smatch matches; read more..

  • Page - 1068

    Section 37.1.1 Regular Expression Notation 1053 For example, we can specify a line starting with zero or more A s followed by one or more B s fol- lowed by an optional C like this: ˆA ∗B+C?$ Examples that match: AAAAAAAAAAAABBBBBBBBBC BC B Examples that do not match: AAAAA // no B AAAABC // initial space AABBCC // too many Cs A part of a pattern is considered a subpattern read more..

  • Page - 1069

    1054 Regular Expressions Chapter 37 The most common character classifications have names: Character Classes alnum Any alphanumeric character alpha Any alphabetic character blank Any whitespace character that is not a line separator cntrl Any control character d Any decimal digit digit Any decimal digit graph Any graphical character lower Any lowercase character print Any printable character punct Any read more..

  • Page - 1070

    Section 37.1.1 Regular Expression Notation 1055 ([[:alpha:]]|_)([[:alnum:]]|_) ∗ // OK, but clumsy [[:alpha:]_][[:alnum:]_] ∗ // OK: include the underscore in the character classes [_[:alpha:]][_[:alnum:]] ∗ // also OK [_[:alpha:]]\w ∗ // \w is equivalent to [_[:alnum:]] Finally, here is a function that uses the simplest version of regex_match() (§37.3.1) to test whether a string is an identifier: read more..

  • Page - 1071

    1056 Regular Expressions Chapter 37 A group (a subpattern) potentially to be represented by a sub_match is delimited by parentheses. If you need parentheses that should not define a subpattern, use (? rather than plain ( . For example: (\s|:|,) ∗(\d∗)// spaces, colons, and/or commas followed by a number Assuming that we were not interested in the characters before the number read more..

  • Page - 1072

    Section 37.2 regex 1057 ˜basic_regex(); // not virtual; basic_regex is not meant to be used as a base class // ... }; The regex_traits are presented in §37.5. Like string , regex is an alias for the version that uses char s: using regex = basic_reg ex<char>; The meaning of regular expression patterns is controlled by syntax_option_type constants defined identically in read more..

  • Page - 1073

    1058 Regular Expressions Chapter 37 basic_regex<C,Tr> Operations (§iso.28.8) r=x Copy assignment: x can be a basic_regex , a C-style string, a basic_string ,oran initializer_list<value_type> r=move(r2) Move assignment r=r.assign(r2) Copyormove r=r.assign(x, ags) Copy or move; set r ’s flags to ags x can be a basic_string , a C-style string, or an initializer_list<value_type> read more..

  • Page - 1074

    Section 37.2.1 Match Results 1059 sub_match<Bi> Operations sub_match sm {}; Default constructor: an empty sequence; constexpr n=sm.length() n is the number of characters matched s=sm Implicit conversion of a sub_match to a basic_string ; s is a basic_string containing the characters matched s=sm.str() s is a basic_string containing the characters matched x=sm.compare(x) Lexicographical comparison: read more..

  • Page - 1075

    1060 Regular Expressions Chapter 37 As for basic_string and basic_ostream , a few standard aliases are provided for the most common match_results : using cmatch = match_results<const c har ∗>; // C-style string using wcmatch = match_results<const wchar_t ∗>; // wide C-style string using smatch = match_results<string::const_iterator>; // string using wsmatch = read more..

  • Page - 1076

    Section 37.2.1 Match Results 1061 regex<C,Tr> Matches and Submatches (continued)(§iso.28.9, §iso.28.10) p=m.begin() p points to the first sub_match of m p=m.end() p points to the one-beyond-the-last sub_match of m p=m.cbegin() p points to the first sub_match of m (const iterator) p=m.cend() p points to the one-beyond-the-last sub_match of m (const iterator) a=m.get_allocator() a is m ’s read more..

  • Page - 1077

    1062 Regular Expressions Chapter 37 Format Substitution Notation $& The match $‘ The prefix $’ The suffix $i The i th submatch, e.g., $1 $ii The ii th submatch, e.g., $12 $$ Not a match, the $ character For an example, see §37.3.3. The details of formatting done by format() are controlled by a set of options (flags): regex<C,Tr> Formatting Options (regex_constants::match_ read more..

  • Page - 1078

    Section 37.3.1 regex_match() 1063 Regular Expression Matching (§iso.28.11.2) Matching is controlled by match_ ag_type options (§37.3) regex_match(b,e ,m,pat, ags) Does the input [b:e) match the regex pattern pat ? place the result in match_results m ; use options ags regex_match(b,e ,m,pat) reg ex_match(b,e ,m,pat,regex_constants::match_default) regex_match(b,e ,pat, ags) Does the input [b:e) match the read more..

  • Page - 1079

    1064 Regular Expressions Chapter 37 while (getline(in,line)) { ++lineno; smatch matches; // submatches go here if (!regex_match(line ,matches,row)) cerr << "bad line: " << lineno << '\n'; int curr_boy = stoi(matches[2]); // for stoi() see §36.3.5 int curr_girl = stoi(matches[3]); int curr_total = stoi(matches[4]); if (curr_boy+curr_girl != curr_total) cerr << "bad r ow sum read more..

  • Page - 1080

    Section 37.3.2 regex_search() 1065 regex pat {"[Ss]tro?u?v?p?stra?o?u?p?b?"}; smatch m; for (string s; cin>>s; ) if (regex_search(s,m,pat)) if (m[0]!="stroustrup" && m[0]!="Stroustrup" ) cout << "Found: " << m[0] << '\n'; Given suitable input, this will output misspellings of Stroustrup , such as: Found: strupstrup Found: Strovstrup Found: stroustrub Found: read more..

  • Page - 1081

    1066 Regular Expressions Chapter 37 void test1() { string input {"x 1 y2 22 zaq 34567"}; regex pat {"(\w+)\s(\d+)"}; // word space number string format {"{$1,$2}\n"}; cout << rege x_replace(input,pat,format); } The output is: {x,1} {y2,22} {zaq,34567} Note the annoying ‘‘spurious’’ spaces at the beginning of the lines. By default, regex_match() copies unmatched read more..

  • Page - 1082

    Section 37.4 Regular Expression Iterators 1067 regex_replace() . If we want to iterate over a sequence of characters doing something for each occur- rence of a pattern, we use a regex_iterator . 37.4.1 regex_iterator A regex_iterator is a bidirectional iterator that searches a sequence for the next match of a pattern when incremented: template<class Bi, class C = typename read more..

  • Page - 1083

    1068 Regular Expressions Chapter 37 void test() { string input = "aa as; asd ++eˆasdf asdfg"; regex pat {R"(\s+(\w+))"}; for (sreg ex_iterator p(input.begin(),input.end(),pat); p!=sregex_iterator{}; ++p) cout << ( ∗p)[1] << '\n'; } This outputs: as asd asdfg Note that we are missing the first word, aa , because it has no preceding whitespace. If we simplify the pattern to read more..

  • Page - 1084

    Section 37.4.2 regex_token_iterator 1069 regex_token_iterator (§iso.28.12.2) regex_token_iterator p {}; p is the end-of-sequence regex_token_iterator p {b,e,pat,x, ags}; x lists the indices of the sub_match es to be included in the iteration or 0 , meaning ‘‘the whole match,’’ or 1 , meaning ‘‘represent each character sequence not matched as a sub_match ’’; x can be an int ,an read more..

  • Page - 1085

    1070 Regular Expressions Chapter 37 splitting a character stream into tokens) because when your pattern matches the token separators, option 1 leaves you with the tokens. For example: void test2() { string s {"1,2 , 3 ,4,5, 6 7"}; // input regex pat {R"(\s ∗,\s∗)"}; // use comma as token separator copy(sreg ex_token_iterator{s.begin(),s.end(),pat, 1)}, sregex_token_iterator{}, read more..

  • Page - 1086

    Section 37.5 regex_traits 1071 regex_traits<C> Operations (§iso.28.7) regex_traits tr {}; Make a default regex_trait<C> n=length(p) n is the number of characters in the C-style string p ; n=char_traits<C>::length() ; static c2=tr.translate(c) c2=c , that is, a no-op c2=tr.translate_nocase(c) use_facet<ctype<C>>(getloc()).tolower(c) ; §39.4.5 s=tr.transform(b,e) s is a string that can read more..

  • Page - 1087

    This page intentionally left blank read more..

  • Page - 1088

    38 I/O Streams What you see is all you get. – Brian W. Kernighan • Introduction • The I/O Stream Hierarchy File Streams; String Streams • Error Handling • I/O Operations Input Operations; Output Operations; Manipulators; Stream State; Formatting • Stream Iterators • Buffering Output Streams and Buffers; Input Streams and Buffers; Buffer Iterators • Advice 38.1 Introduction The I/O read more..

  • Page - 1089

    1074 I/O Streams Chapter 38 An istream converts a stream of characters (bytes) to typed objects: 'c' 123 (123,45) istream stream buffer ‘‘Somewhere’’ Typed values: Byte sequences: An iostream is a stream that can act as both an istream and an ostream . The buffers in the diagrams are stream buffers (streambufs; §38.6). Y ou need them to define a mapping from an iostream to a read more..

  • Page - 1090

    Section 38.1 Introduction 1075 • Are locale sensitive (Chapter 39) • Are efficient (though their potential is not always fully realized) • Are interoperable with C-style stdio (§43.3) • Include formatted, unformatted, and character-level operations The basic_iostream is defined based on basic_istream (§38.6.2) and basic_ostream (§38.6.1): template<typename C, typename Tr = read more..

  • Page - 1091

    1076 I/O Streams Chapter 38 38.2 The I/O Stream Hierarchy An istream can be connected to an input device (e.g., a keyboard), a file, or a string . Similarly, an ostream can be connected to an output device (e.g., a text window or an HTML engine), a file, or a string . The I/O stream facilities are organized in a class hierarchy: ios_base basic_ios<> basic_istream<> read more..

  • Page - 1092

    Section 38.2.1 File Streams 1077 The set of fstream operations is fairly simple: basic_fstream<C,Tr> (§iso.27.9) fstream fs {}; fs is a file stream not attached to a file fstream fs {s,m}; fs is a file stream opened for a file called s with mode m ; s can be a string or a C-style string fstream fs {fs2}; Move constructor: fs2 is moved to fs ; fs2 becomes unattached read more..

  • Page - 1093

    1078 I/O Streams Chapter 38 fstream ifs; // ‘‘i’’ for ‘‘input’’ implying ios::in ifs.open("source",ios_base::in); if (!ifs) error("couldn't open 'source' for reading"); For positioning in a file, see §38.6.1. 38.2.2 String Streams In <sstream> , the standard library provides streams to and from a string : • istringstream s for reading from a string • read more..

  • Page - 1094

    Section 38.2.2 String Streams 1079 In addition, the string streams override the basic_ios protected virtual functions under ow() , pbackfail() , over ow() , setbuf() , seekoff() , and seekpos() (§38.6). A string stream does not have copy operations. If you want two names to refer to the same string stream, use a reference or a pointer. There are six string stream aliases defined read more..

  • Page - 1095

    1080 I/O Streams Chapter 38 38.3 Error Handling An iostream can be in one of four states, defined in basic_ios from <ios> (§38.4.4): Stream States (§iso.27.5.5.4) good() The previous iostream operations succeeded eof() We hit end-of-input (‘‘end-of-file’’) fail() Something unexpected happened (e.g., we looked for a digit and found 'x' ) bad() Something unexpected and serious read more..

  • Page - 1096

    Section 38.3 Error Handling 1081 void use(istream& is) { Io_guard guard(is.ios_base::badbit); // ... use is ... } catch (ios_base::badbit) { // ... bail out! ... } I tend to use exceptions to handle iostream errors that I don’t expect to be able to recover from. That usually means all bad() exceptions. 38.4 I/O Operations The complexity of the I/O operations reflects tradition, the read more..

  • Page - 1097

    1082 I/O Streams Chapter 38 To users of an istream , the sentry class is an implementation detail. It provides common code for standard-library and user-defined input operations. Code that needs to be executed first (the ‘‘prefix code’’) – such as flushing a tied stream – is provided as the sentry ’s constructor. For example: template<typename C, typename Tr = read more..

  • Page - 1098

    Section 38.4.1.1 Formatted Input 1083 By default >> skips whitespace. For example: for (int i; cin>>i && 0<i;) cout << i << '\n'; This will take a sequence of whitespace-separated positive integers and print them one to a line. Skipping of whitespace can be suppressed using noskipws (§38.4.5.2). The input operations are not virtual . That is, a user cannot do read more..

  • Page - 1099

    1084 I/O Streams Chapter 38 void f() // low-level, old-style line read { char word[MAX_WORD][MAX_LINE]; // MAX_WORD arrays of MAX_LINE char each int i = 0; while(cin.getline(word[i++],MAX_LINE,'\n') && i<MAX_WO RD) /* do nothing */ ; // ... } For these functions, it is not immediately obvious what terminated the read: • We found the terminator. • We read the maximum number of read more..

  • Page - 1100

    Section 38.4.2 Output Operations 1085 explicit basic_ostream(basic_streambuf<char_type ,Tr> ∗ sb); virtual ˜basic_ostream(); // release all resources class sentry; // see §38.4.1 // ... protected: // move but no copy: basic_ostream(const basic_ostream& rhs) = delete; basic_ostream(basic_ostream&& rhs); basic_ostream& operator=(basic_ostream& rhs) = delete; basic_ostream& operator=(const read more..

  • Page - 1101

    1086 I/O Streams Chapter 38 Versions of operator << for user-defined types are usually trivial to write: template<typename T> struct Named_val { string name; T value; }; ostream& operator<<(ostream& os, const Named_val& n v) { return os << '{' << nv.name << ':' << nv.value << '}'; } This will work for every Named_val<X> where X has a << defined. read more..

  • Page - 1102

    Section 38.4.2.1 Virtual Output Functions 1087 This integrates the virtual put() into the framework provided by ostream and << . The technique is generally useful to provide operations that act like virtual functions, but with the run-time selection based on their second argument. This is similar to the technique that under the name double dis- patch is often used to select an read more..

  • Page - 1103

    1088 I/O Streams Chapter 38 38.4.4 Stream State In <ios> , the standard library defines the base class ios_base defining most of the interface to a stream class: template<typename C, typename Tr = char_traits<C>> class basic_ios : public ios_base { public: using char_type = C; using int_type = typename Tr::int_type; using pos_type = typename Tr::pos_type; using off_type = read more..

  • Page - 1104

    Section 38.4.4 Stream State 1089 guarantees that the iostream and stdio (§43.3) I/O operations share b uffers. A call of sync_with_stdio(false) before the first stream I/O operation prevents buffer sharing and can improve I/O performance significantly on some implementations. Note that ios_base has no copy or move operations. ios_base Stream State iostate Member Constants (§iso.27.5.3.1.3) badbit read more..

  • Page - 1105

    1090 I/O Streams Chapter 38 The seekg() (§38.6.2) and seekp() (§38.6.2) operations require a direction: ios_base Direction seekdir Member Constants (§iso.27.5.3.1.5) beg Seek from beginning of current file cur Seek from current position end Seek backward from end of current file Classes derived from basic_ios format output and extract objects based on the information stored in their basic_io . The read more..

  • Page - 1106

    Section 38.4.4 Stream State 1091 basic_ios<C,Tr> (continued) (§iso.27.5.5) c2=widen(c) c2 is a char_type value obtained by converting c of char type : use_facet<ctype<char_type>>(g etloc()).widen(c)) ios.init(p) Set ios to the default state and use the stream buffer pointed to by p ; protected ios.set_rdbuf(p) Make ios use the stream buffer pointed to by p ; protected ios.move(ios2) Copy read more..

  • Page - 1107

    1092 I/O Streams Chapter 38 enum event { erase_event, imbue_event, copyfmt_event }; using event_callback = void ( ∗)(event, ios_base&, int index); 38.4.5 Formatting The format of stream I/O is controlled by a combination of object type, stream state (§38.4.4), for- mat state (§38.4.5.1), locale information (Chapter 39), and e xplicit operations (e.g., manipulators; §38.4.5.2). 38.4.5.1 Formatting State read more..

  • Page - 1108

    Section 38.4.5.1 Formatting State 1093 ios_base Formatting fmt ags Operations (§iso.27.5.3.2) f=ios. ags() f is ios ’s formatting flags f2=ios. ags(f) Set ios ’s formatting flags to f ; f2 is the old value of the flags f2=ios.setf(f) Set ios ’s formatting flags to f ; f2 is the old value of the flags f2=ios.setf(f,m) f2=ios.setf(f&m) ios.unsetf(f) Clear the flags f in ios read more..

  • Page - 1109

    1094 I/O Streams Chapter 38 cout.width(0); // ‘‘as many characters as needed’’ A call width(n) sets the minimum number of characters to n . If more characters are provided, they will all be printed. For example: cout.width(4); cout << "abcdef"; // print abcdef It does not truncate the output to abcd . It is usually better to get the right output looking ugly read more..

  • Page - 1110

    Section 38.4.5.2 Standard Manipulators 1095 I/O Manipulators from <ios> (continued) (§iso.27.5.6, §iso.27.7.4) s<<internal Pad where marked in formatting pattern s<<left Pad after value s<<right Pad before value s<<dec Integer base is 10 s<<hex Integer base is 16 s<<oct Integer base is 8 s<< xed Floating-point format dddd.dd s<<scienti c Scientific format read more..

  • Page - 1111

    1096 I/O Streams Chapter 38 I/O Manipulators from <iomanip> (§iso.27.5.6, §iso.27.7.4) s<<resetios ags(f) Clear flags f s<<setios ags(f) Set flags f s<<setbase(b) Output integers in base b s<<set ll(int c) Make c the fill character s<<setprecision(n) Precision is n digits s<<setw(n) Next field width is n char is>>get_money(m,intl) Read from is using is ’s read more..

  • Page - 1112

    Section 38.4.5.2 Standard Manipulators 1097 If you want to explicitly deal with whitespace (e.g., to make a newline significant) and still use >> , noskipws and >>ws become a convenience. 38.4.5.3 User-Defined Manipulators A programmer can add manipulators in the style of the standard ones. Here, I present an additional style that I have found useful for formatting read more..

  • Page - 1113

    1098 I/O Streams Chapter 38 public: explicit Form(int p =6, ios_base::fmt ags f =0, int w =0) : prc{p}, fmt{f}, wdt{w} {} Bound_form Form::operator()(double d) const // make a Bound_for m for *this and d { return Bound_form{ ∗this,d}; } Form& scienti c() { fmt = ios_base::scienti c; return ∗this; } Form& xed() { fmt = ios_base:: xed; return ∗this; } Form& ge neral() { read more..

  • Page - 1114

    Section 38.5 Stream Iterators 1099 template<typename T , typename C = char, typename Tr = char_traits<C>, typename Distance = ptrdiff_t> class istream_iterator :public iterator<input_iterator_tag, T , Distance , const T ∗, const T&> { using char_type = C; using traits_type = Tr; using istream_type = basic_istream<C,Tr>; // ... }; template<typename T , typename C = char, read more..

  • Page - 1115

    1100 I/O Streams Chapter 38 38.6 Buffering Conceptually, an output stream puts characters into a buffer. Sometime later, the characters are then written to (‘‘flushed to’’) wherever they are supposed to go. Such a buffer is called a stream- buf . Its definition is found in <streambuf> . Different types of streambuf s implement different buffering strategies. Typically, the read more..

  • Page - 1116

    Section 38.6 Buffering 1101 public basic_streambuf<C,Tr> Operations (§iso.27.6.3) sb.˜basic_streambuf() Destructor: release all resources; virtual loc=sb.g etloc() loc is sb ’s locale loc2=sb.pubimbue(loc) sb.imbue(loc) ; loc2 is a pointer to the previous locale psb=sb.pubsetbuf(s,n) psb=sb.setbuf(s,n) pos=sb.pubseekoff(n,w,m) pos=sb.seekoff(n,w,m) pos=sb.pubseekoff(n,w) pos=sb.seekoff(n,w) pos=sb.pubseekpos(n,m) read more..

  • Page - 1117

    1102 I/O Streams Chapter 38 Overflow are handled by the virtual functions over ow() , under ow() , and u ow() . For a use of positioning, see §38.6.1. The put-and-get interface is separated into a public and a protected one: public Put and Get basic_streambuf<C,Tr> Operations (§iso.27.6.3) (continues) n=sb.in_avail() If a read position is available, n=sb.egptr() sb.gptr() ; otherwise read more..

  • Page - 1118

    Section 38.6 Buffering 1103 protected Put and Get basic_streambuf<C,Tr> Operations (continued) (§iso.27.6.3) sb.setp(b,e) The put area is [b,e) the current put pointer is b pc=sb.pbase() [pc:sb.epptr()) is the put area pc=sb.pptr() pc is the put pointer pc=sb.epptr() [sb.pbase(),pc) is the put area sb.pbump(n) Add one to the put pointer n2=sb.xsgetn(s,n) s is a const char ∗;do sb.sgetc( ∗p) read more..

  • Page - 1119

    1104 I/O Streams Chapter 38 The seekp() functions are used to position an ostream for writing. The p suffix indicates that it is the position used for putting characters into the stream. These functions have no effect unless the stream is attached to something for which positioning is meaningful, such as a file. The pos_type represents a character position in a file, and read more..

  • Page - 1120

    Section 38.6.2 Input Streams and Buffers 1105 streamsize readsome(C ∗ p, streamsize n); // read at most n char }; The basic_istream functions override their equivalents in the basic_istream ’s basic_ios base. The positioning functions work like their ostream counterparts (§38.6.1). The g suffix indicates that it is the position used for getting characters from the stream. The p and g read more..

  • Page - 1121

    1106 I/O Streams Chapter 38 The reference member of the iterator base is not used and is consequently left unspecified. If you use an istreambuf_iterator as an input iterator, its effect is like that of other input iterators: a stream of characters can be read from input using c= ∗p++: istreambuf_iterator<C,Tr> (§iso.24.6.3) istreambuf_iterator p {}; p is an end-of-stream read more..

  • Page - 1122

    Section 38.6.3.2 ostreambuf_iterator 1107 ostreambuf_iterator<C,Tr> (continued) (§iso.24.6.4) p=c If !p.failed() call the streambuf ’s sputc(c) ∗p Do nothing ++p Do nothing p++ Do nothing p.failed() Has a sputc() on p ’s streambuf reached eof ? noexcept 38.7 Advice [1] Define << and >> for user-defined types with values that have meaningful textual representa- tions; §38.1, read more..

  • Page - 1123

    1108 I/O Streams Chapter 38 [29] Don’t use endl except possibly for aesthetic reasons; §38.4.5.2. [30] If iostream formatting gets too tedious, write your own manipulators; §38.4.5.3. [31] You can achieve the effect (and efficiency) of a ternary operator by defining a simple function object; §38.4.5.3. read more..

  • Page - 1124

    39 Locales When in Rome, do as the Romans do. – Pro verb • Handling Cultural Differences • Class locale Named locale s; Comparing string s • Class facet Accessing facet sina locale ; A Simple User-defined facet ; Uses of locale s and facet s • Standard facet s string Comparison; Numeric Formatting; Money Formatting; Date and Time Formatting; Character Classification; Character Code read more..

  • Page - 1125

    1110 Locales Chapter 39 on a system, independently of which programming language they are written in. Thus, the C++ standard-library notion of a locale can be seen as a standard and portable way for C++ programs to access information that has very different representations on different systems. Among other things, a C++ locale is an interface to system information that is read more..

  • Page - 1126

    Section 39.1 Handling Cultural Differences 1111 12,5 means twelve and a half) and write it according to American conventions? We can define locale s and I/O operations so that cpy() can be used to convert between conventions: void f(istream& n, ostream& fout, istream& n2, ostream& fout2) { n.imbue(locale{"en_US.UTF 8"}); // American English fout.imbue(locale{"fr_FR.UTF read more..

  • Page - 1127

    1112 Locales Chapter 39 [3] A locale is used in operations (e.g., I/O and sorting) from which people demand run-time efficiency. [4] A locale must be invisible to the majority of programmers who want to benefit from facil- ities ‘‘doing the right thing’’ without having to know exactly what ‘‘the right thing’’ is or how it is achieved. [5] A locale must be available read more..

  • Page - 1128

    Section 39.2 Class locale 1113 If a locale of a given name or a facet referred to doesn’t exist, the locale operation naming it throws a runtime_error . Naming of locale s is a bit curious. When you make a new locale from another plus a facet and the resulting locale has a name, that name is implementation-defined. Often, such an implementa- tion-defined name includes the read more..

  • Page - 1129

    1114 Locales Chapter 39 A programmer can replace facet s from existing categories (§39.4, §39.4.2.1). However, there is no way for a programmer to define a new category. The notion of ‘‘category’’ applies to standard- library facets only, and it is not extensible. Thus, a facet need not belong to any category, and many user-defined facets do not. If a locale x does read more..

  • Page - 1130

    Section 39.2.1 Named locale s 1115 GNU Locale Name Examples (Based on POSIX) ja_JP Japanese for Japan da_DK Danish for Denmark en_DK English for Denmark de_CH German for Switzerland de_DE German for Germany en_GB English for Great Britain en_US English for the U.S.A. fr_CA French for Canada de_DE German for Germany de_DE@euro German for Germany with the euro symbol de_DE.utf8 German for Germany read more..

  • Page - 1131

    1116 Locales Chapter 39 reading a file). Alternatively, a program can request a user to specify alternative locales by entering a string. For example: void user_set_locale(const string& question) { cout << question; // e.g., "If you w ant to use a different locale, please enter its name" string s; cin >> s; locale::global(locale{s}); // set global locale as specified by read more..

  • Page - 1132

    Section 39.2.1.1 Constructing New locale s 1117 Here, loc1 is a copy of the POSIX locale modified to use loc ’s monetary facet s (§39.4.3). Similarly, loc2 is a copy of the C locale modified to use a My_money_io (§39.4.3.1). The resulting locale s can be represented like this: classic() : compare() hash() ... collate<char> : decimal_point() curr_symbol() ... numpunct<char> : read more..

  • Page - 1133

    1118 Locales Chapter 39 The locale::id member type is used by locale to identify facet types (§39.3). There is no way of modifying a locale . Instead, the locale operations provide ways of making new locale s from existing ones. The fact that a locale is immutable after it has been created is essential for run-time efficiency. This allows someone using a locale to call read more..

  • Page - 1134

    Section 39.3 Class facet 1119 class locale::facet { protected: explicit facet(size_t refs = 0); virtual ˜facet(); facet(const facet&) = delete; void operator=(const facet&) = delete; }; The facet class is designed to be a base class and has no public functions. Its constructor is pro- tected to prevent the creation of ‘‘plain facet ’’ objects, and its destructor is virtual to read more..

  • Page - 1135

    1120 Locales Chapter 39 void f(const locale& my_locale) { char c = use_facet<numpunct<char>>(my_locale).decimal_point() // use standard facet // ... if (has_facet<Encrypt>(my_locale)) { // does my_locale contain an Encrypt facet? const Encrypt& f = use_facet<Encrypt>(my_locale); // retrieve Encr ypt facet const Crypto c = f.g et_crypto(); // use Encrypt facet // ... } // ... } read more..

  • Page - 1136

    Section 39.3.2 A Simple User-Defined facet 1121 For simplicity, this facet is limited to string sof char s. The Season_io class provides a general and abstract interface for all Season_io facets. To define the I/O representation of a Season for a particular locale , we derive a class from Season_io , defining to_str() and from_str() appropriately. Output of a Season is easy. If the read more..

  • Page - 1137

    1122 Locales Chapter 39 // use the default locale (no Season_io facet) implies integer I/O: cin >> x; cout << x << endl; locale loc(locale(),new US_season_io{}); cout.imbue(loc); // use locale with Season_io facet cin.imbue(loc); // use locale with Season_io facet cin >> x; cout << x << endl; } Given the input 2 summer this program responds: 2 summer To get this, we read more..

  • Page - 1138

    Section 39.3.2 A Simple User-Defined facet 1123 bool US_season_io::from_str(const string& s, Season& x) const { const string ∗ p= nd(begin(seasons),end(seasons),s); if (p==end) return false; x = Season(p begin(seasons)); return true; } Note that because US_season_io is simply an implementation of the Season_io interface, I did not define an id for US_season_io . In fact, if we want US_season_io read more..

  • Page - 1139

    1124 Locales Chapter 39 39.4 Standard facet s In <locale> , the standard library provides these facet s: Standard facet s (§iso.22.3.1.1.1) collate String comparison collate<C> §39.4.1 numeric Numeric formatting numpunct<C> §39.4.2 num_g et<C,In> num_put<C,Out> monetary Money formatting moneypunct<C> §39.4.3 moneypunct<C,International> money_g et<C,In> money_put<C,Out> time read more..

  • Page - 1140

    Section 39.4 Standard facet s 1125 sort(v.begin(),v.end(),collate_byname{"da_DK"}); // sor t using character comparison from "da_DK" The idea is to pick a version of a standard facet from a named locale (§39.2.1) in the program’s execution environment. This implies that _byname constructors are very slow compared to con- structors that do not need to consult the environment. It read more..

  • Page - 1141

    1126 Locales Chapter 39 39.4.1 string Comparison The standard collate facet provides ways of comparing arrays of characters: template<class C> class collate : public locale::facet { public: using char_type = C; using string_type = basic_string<C>; explicit collate(size_t = 0); int compare(const C ∗ b, const C ∗ e, const C ∗ b2, const C ∗ e2) const { return read more..

  • Page - 1142

    Section 39.4.1 string Comparison 1127 The transform() function produces a string that, when compared to another transform() ed string, gives the same result as comparing the strings. That is: cf.compare(cf.transform(s),cf.transform(s2)) == cf.compare(s,s2) The purpose of transform() is to allow optimization of code in which a string is compared to many others. This is useful when implementing a read more..

  • Page - 1143

    1128 Locales Chapter 39 using Col = collate<char>; const Col& global {use_facet<Col>(locale{})}; // from the current global locale int i0 {global.compare(s1b,s1e,s2b,s2e)}; const Col& my_coll {use_facet<Col>(locale{""})}; // from my preferred locale int i1 {my_coll.compare(s1b,s1e ,s2b,s2e)}; const Col& n_coll {use_facet<Col>(locale{name})}; // from a named locale int i2 read more..

  • Page - 1144

    Section 39.4.1.1 Named collate 1129 protected: ˜collate_byname(); // note: protected destructor int do_compare(const C ∗ b, const C ∗ e, const C ∗ b2, const C ∗ e2) const override; string_type do_transform(const C ∗ b, const C ∗ e) const override; long do_hash(const C ∗ b, const C ∗ e) const override; }; Thus, a collate_byname can be used to pick out a collate from a read more..

  • Page - 1145

    1130 Locales Chapter 39 char do_thousands_sep() const override { return '_'; } // underscore string do_grouping() const override { return "\003"; } // 3-digit groups }; void f() { cout << "style A: " << 12345678 << " ∗∗∗ " << 1234567.8 << " ∗∗∗ "<< xed << 1234567.8 << '\n'; cout << default oat; // reset floating read more..

  • Page - 1146

    Section 39.4.2.2 Numeric Output 1131 The default specialization of num_put (the one where the iterator used to access characters is of type ostreambuf_iterator<C> ) is part of the standard locale s (§39.4). To write elsewhere using a num_put , we must define an appropriate specialization. For example, here is a very simple num_put for writing into a string : template<class C> read more..

  • Page - 1147

    1132 Locales Chapter 39 catch (...) { handle_ioexception( ∗this); } return ∗this; } A lot is going on here. The sentry ensures that all prefix and suffix operations are performed (§38.4.1). W e get the ostream ’s locale by calling its member function getloc() (§38.4.5.1). W e extract num_put from that locale using use_facet (§39.3.1). That done, we call the appropriate put() function read more..

  • Page - 1148

    Section 39.4.2.3 Numeric Input 1133 39.4.2.3 Numeric Input When reading from a stream buffer (§38.6), an istream relies on the num_g et facet: num_g et<In = istreambuf_iterator<C>> facet (§iso.22.4.2.1) Read [b:e) into v , using formatting rules from s , reporting errors by setting r In get(In b, In e, ios_base& s, ios_base::iostate& r, bool& v) const; In get(In b, In e, read more..

  • Page - 1149

    1134 Locales Chapter 39 I took care not to modify the target of the >> unless the read operation succeeded. Unfortunately, that cannot be guaranteed for all input operations. Exceptions enabled for the istream will be thrown by setstate() in case of error (§38.3). By defining a numpunct , such as My_punct from §39.4.2.1, we can read using nonstandard punc- tuation. For example: void read more..

  • Page - 1150

    Section 39.4.3 Money Formatting 1135 value= 1234567 amount= $12345.67 value= 1234567 amount= 12345,67 DKK value= 1234567 amount= CAD 12345,67 value= 1234567 amount= $ 12345.67 value= 1234567 amount= €12345.67 value= 1234567 amount= (CHF12345,67) For money, accuracy to the smallest currency unit is usually considered essential. Consequently, I adopted the common convention of having the integer read more..

  • Page - 1151

    1136 Locales Chapter 39 The moneypunct member functions define the layout of money input and output: moneypunct<C,International>> facet (§iso.22.4.6.3) C decimal_point() const; E.g., ’.’ C thousands_sep() const; E.g., ’,’ string grouping() const; E.g., "" meaning ‘‘no grouping’’ string_type curr_symbol() const; E.g., "$" string_type positive_sign() const; E.g., "" read more..

  • Page - 1152

    Section 39.4.3.1 Money Punctuation 1137 Representing a negative number using parentheses is achieved by having negative_sign() return a string containing the two characters () . The first character of a sign string is placed where sign is found in the pattern, and the rest of the sign string is placed after all other parts of the pattern. The most common use of this facility read more..

  • Page - 1153

    1138 Locales Chapter 39 money_put<C,Out = ostreambuf_iterator<C>> facet (§iso.22.4.6.2) Put value v into buffer position b Out put(Out b, bool intl, ios_base& s, C ll, long double v) const; Out put(Out b, bool intl, ios_base& s, C ll, const string_type& v) const; The intl argument indicates whether a standard four-character ‘‘international’’ currency symbol or a ‘‘local’’ read more..

  • Page - 1154

    Section 39.4.3.3 Money Input 1139 int main() { Money m; while (cin>>m) cout << m << "\n"; } The output of this simple program should be acceptable as its input. Furthermore, the output pro- duced by a second run given the output from a first run should be identical to its input. A plausible input operator for Money would be: istream& operator>>(istream& read more..

  • Page - 1155

    1140 Locales Chapter 39 39.4.4.1 time_put A time_put facet takes a point in time presented as a tm and produces a sequence of characters rep- resenting it using strftime() (§43.6) or an equivalent. time_put<C,Out = ostreambuf_iterator<C>> facet (§iso.22.4.5.1) Out put(Out s, ios_base& f, C ll, const tm ∗ pt, const C ∗ b, const C ∗ e) const; Out put(Out s, ios_base& f, C read more..

  • Page - 1156

    Section 39.4.4.2 time_get 1141 time_get<C,In> facet (§iso.22.4.5.1) Read from [b:e) into ∗pt dateorder do_date_order() const; In get_time(In b, In e, ios_base& ib, ios_base::iostate& err, tm ∗ pt) const; In get_date(In b, In e, ios_base& ib, ios_base::iostate& err, tm ∗ pt) const; In get_weekday(In b, In e, ios_base& ib, ios_base::iostate& err, tm ∗ pt) const; In read more..

  • Page - 1157

    1142 Locales Chapter 39 istream& operator>>(istream& is, Date& d) { if (istream::sentry guard{is}) { ios_base::iostate err = goodbit; struct tm t; use_facet<time_get<char>>(is.g etloc()).g et_date(is,0,is,err,&t); // read into t if (!err) { Month m = static_cast<Month>(t.tm_mon+1); d = Date(t.tm_day,m,t.tm_year+1900); } is.setstate(err); } return is; } The +1900 is needed because year read more..

  • Page - 1158

    Section 39.4.5 Character Classification 1143 template<class C> class ctype : public locale::facet, public ctype_base { public: using char_type = C; // ... }; This mask doesn’t depend on a particular character type. Consequently, this enumeration is placed in a (non-template) base class. Clearly, mask reflects the traditional C and C++ classification (§36.2.1). However, for different read more..

  • Page - 1159

    1144 Locales Chapter 39 for(auto p = s.begin(); p!=s.end(); ++p) if (ct.is(ctype_base::space, ∗p)) // whitespace as defined by ct ++i; return i; } Note that it is also possible to use is() to check whether a character belongs to one of a number of classifications. For example: ct.is(ctype_base::space|ctype_base::punct,c); // is c whitespace or punctuation in ct? A call is(b,e,v) read more..

  • Page - 1160

    Section 39.4.5 Character Classification 1145 char EBCDIC_e = use_facet<ctype<char>>(ebcdic).widen('e'); A call widen(b,e,v) takes each character in the range [b:e) and places a widened version in the corre- sponding position in the array v . A call narrow(ch,def) produces a char value corresponding to the character ch from the C type. Again, ‘‘the simplest reasonable transformation’’ read more..

  • Page - 1161

    1146 Locales Chapter 39 39.4.6 Character Code Conversion Sometimes, the representation of characters stored in a file differs from the desired representation of those same characters in main memory. For example, Japanese characters are often stored in files in which indicators (‘‘shifts’’) indicate to which of the four common character sets (kanji, katakana, hiragana, and romaji) a read more..

  • Page - 1162

    Section 39.4.6 Character Code Conversion 1147 codecvt<In,Ex,SS> facet (§iso.22.5) using CI = const In; using CE = const Ex; result in(SS& st, CE ∗ b, CE ∗ e, CE ∗& next, In ∗ b2, In ∗ e2, In ∗& next2) const; result out(SS& st, CI ∗ b, CI ∗ e, CI ∗& next, Ex ∗ b2, Ex ∗ e2, Ex ∗& next2) const; result unshift(SS& st, Ex ∗ b, Ex read more..

  • Page - 1163

    1148 Locales Chapter 39 The state_type argument st indicates the state of the input character sequence at the start of the call of in(). This is significant when the external character representation uses shift states. Note that st is a (non-const) reference argument: at the end of the call, st holds the shift state of the input sequence. This allows a programmer to deal with read more..

  • Page - 1164

    Section 39.4.6 Character Code Conversion 1149 result do_unshift(State&, E ∗ to, E ∗ to_end, E ∗& to_next) const override { return ok; } int do_encoding() const noexcept override { return 1; } bool do_always_noconv() const noexcept override { return false; } int do_length(const State&, const E ∗ from, const E ∗ from_end, size_t max) const override; int do_max_length() const read more..

  • Page - 1165

    1150 Locales Chapter 39 class messages_base { public: using catalog = /* implementation-defined integer type */; // catalog identifier type }; template<class C> class messages : public locale::facet, public messages_base { public: using char_type = C; using string_type = basic_string<C>; // ... }; The messages interface is comparatively simple: messages<C> facet (§iso.22.4.7.1) catalog read more..

  • Page - 1166

    Section 39.4.7 Messages 1151 void do_close(catalog cat) const { if (catalogs.size()<=cat) catalogs.erase(catalogs.begin()+cat); } ˜My_messages() { delete &catalogs; } }; All messages ’ member functions are const , so the catalog data structure (the vector<Set> ) is stored outside the facet . A message is selected by specifying a catalog, a set within that catalog, and a message string read more..

  • Page - 1167

    1152 Locales Chapter 39 int main() // a trivial test { if (!has_facet<My_messages>(locale())) { cerr << "no messages facet found in" << locale().name() << '\n'; exit(1); } const messages<char>& m = use_facet<My_messages>(locale()); extern string message_director y; // where I keep my messages auto cat = m.open(message_director y,locale()); if (cat<0) { cerr << read more..

  • Page - 1168

    Section 39.4.7.1 Using Messages from Other facet s 1153 class Season_io : public locale::facet { const messages<char>& m; // message directory messages_base::catalog cat; // message catalog public: class Missing_messages { }; Season_io(size_t i = 0) : locale::facet(i), m(use_facet<Season_messages>(locale())), cat(m.open(message_director y,locale())) { if (cat<0) throw Missing_messages(); } ˜Season_io() read more..

  • Page - 1169

    1154 Locales Chapter 39 template<class C> class messages_byname : public messages<C> { // ... }; 39.5 Convenience Interfaces Beyond simply imbuing an iostream , the locale facilities can be complicated to use. Consequently, convenience interfaces are provided to simplify notation and minimize mistakes. 39.5.1 Character Classification The most common use of the ctype facet is to inquire read more..

  • Page - 1170

    Section 39.5.2 Character Conversions 1155 39.5.2 Character Conversions Case conversions can be locale sensitive: Character Conversion (§iso.22.3.3.2.1) c2= toupper(c,loc) use_facet<ctype<C>>(loc).toupper(c) c2= tolower(c,loc) use_facet<ctype<C>>(loc).tolower(c) 39.5.3 String Conversions Character code conversions can be locale sensitive. Class template wstring_conver t performs con- versions between a read more..

  • Page - 1171

    1156 Locales Chapter 39 wstring_conver t<Codecvt,Wc,Wa,Ba> (§iso.22.3.3.2.2) ws=cvt.from_bytes(c) ws contains the char c converted to Wc s ws=cvt.from_bytes(s) ws contains the char sof s converted to Wc s; s is a C-style string or a string ws=cvt.from_bytes(b,e) ws contains the char sof[b:e) converted to Wc s s=cvt.to_bytes(wc) s contains wc converted to char s s=cvt.to_bytes(ws) s contains the Wc read more..

  • Page - 1172

    Section 39.5.4 Buffer Conversions 1157 wbuffer_conver t<Codecvt,C,Tr> (§iso.22.3.3.2.3) wbuffer_conver t wb {psb,pcvt,state}; wb converts from the streambuf ∗psb, using converter ∗pcvt and initial conversion state state wbuffer_conver t wb {psb,pcvt}; wbuffer_conver t wb {psb,pcvt,state_type{}}; wbuffer_conver t wb {psb}; wbuffer_conver t wb {psb,new Codecvt{}}; wbuffer_conver t wb {}; wbuffer_conver t read more..

  • Page - 1173

    This page intentionally left blank read more..

  • Page - 1174

    40 Numerics The purpose of computing is insight, not numbers. – R. W. Hamming ... but for the student, numbers are often the best road to insight. – A. Ralston • Introduction • Numerical Limits Limit Macros • Standard Mathematical Functions • complex Numbers • A Numerical Array: valarray Constructors and Assignments; Subscripting; Operations; Slices; slice_array ; Generalized Slices read more..

  • Page - 1175

    1160 Numerics Chapter 40 structures are needed as part of a computation, C++’s strengths become relevant. The net effect is that C++ is widely used for scientific, engineering, financial, and other computation involving sophisticated numerics. Consequently, facilities and techniques supporting such computation have emerged. This chapter describes the parts of the standard library that read more..

  • Page - 1176

    Section 40.2 Numerical Limits 1161 The real information is in the specializations. Each implementation of the standard library provides a specialization of numeric_limits for each fundamental numeric type (the character types, the inte- ger types, the floating-point types, and bool ) but not for any other plausible candidates such as void , enumerations, or library types (such as read more..

  • Page - 1177

    1162 Numerics Chapter 40 static constexpr oat quiet_NaN() noexcept { return /* some value */; } static constexpr oat signaling_NaN() noexcept { return /* some value */; } static constexpr oat denorm_min() noexcept { return min(); } static const int min_exponent = 125; static const int min_exponent10 = 37; static const int max_exponent = +128; static const int max_exponent10 = +38; read more..

  • Page - 1178

    Section 40.2.1 Limit Macros 1163 Similarly, <c oat> and < oat.h> define macros describing properties of floating-point numbers: Floating-Point Limit Macros (_iso.diff.library_, abbreviated) FLT_MIN Smallest positive oat value (e.g., 1.175494351e 38F ) FLT_MAX Largest oat value (e.g., 3.402823466e+38F ) FLT_DIG Number of decimal digits of precision of a oat (e.g., 6 ) FLT_MAX_10_EXP Largest read more..

  • Page - 1179

    1164 Numerics Chapter 40 pow(numeric_limits<double>::max(),2); if (errno == ERANGE) cerr << "result of pow() too large to represent as a double"; } For historical reasons, a few mathematical functions are found in <cstdlib> rather than in <cmath> : More Mathematical Functions (§iso.26.8) n2=abs(n) Absolute value; n is int , long ,or long long ; n2 has the same type read more..

  • Page - 1180

    Section 40.4 complex Numbers 1165 Scalar imag() const { return im; } // imaginar y par t void imag(Scalar i) { im = i; } template<typename X> complex(const complex<X>&); complex<T>& operator=(const T&); complex& operator=(const complex&); template<typename X> complex<T>& operator=(const complex<X>&); complex<T>& operator+=(const T&); template<typename X> read more..

  • Page - 1181

    1166 Numerics Chapter 40 40.5 A Numerical Array: valarray Much numeric work relies on relatively simple single-dimensional vectors of floating-point values. In particular, such vectors are well supported by high-performance machine architectures, libraries relying on such vectors are in wide use, and very aggressive optimization of code using such vec- tors is considered essential in many read more..

  • Page - 1182

    Section 40.5.1 Constructors and Assignments 1167 valarray<int> v2( 1,2000); // 2000 elements with value −1 valarray<double> v3(100,9.8064); // bad mistake: floating-point valarray size valarray<double> v4 = v3; // v4 has v3.size() elements valarray<int> v5 { 1,2000}; // two elements In the two-argument constructors, the value comes before the number of elements. This differs from the read more..

  • Page - 1183

    1168 Numerics Chapter 40 In addition to this conventional assignment, it is possible to assign a scalar to a valarray. For example, v=7 assigns 7 to every element of the valarray v . This may be surprising to some program- mers and is best understood as an occasionally useful degenerate case of the operator assignment operations. For example: valarray<int> v {1,2,3,4,5,6,7,8}; v read more..

  • Page - 1184

    Section 40.5.2 Subscripting 1169 •A gslice of a non-const valarray : gslice_array<T> operator[](const gslice&); // references to elements // ... valarray<char> v0 {"abcdefghijklmnop",16}; valarray<char> v1 {"ABCDE",5}; const valarray<siz e_t> len {2,3}; const valarray<siz e_t> str {7,2}; v0[gslice(3,len,str)] = v1; // v0=={"abcAeBgCijDlEnFp",16} •A valarray<bool> (a read more..

  • Page - 1185

    1170 Numerics Chapter 40 valarray<T> Member Operations (§iso.26.6.2.8) va.swap(va2) Exchange elements of va and va2 ; noexcept; n=va.siz e() n is the number of elements of va t=va.sum() t is the sum of elements of va computed using += t=va.min() t is the smallest element of va found using < t=va.max() t is the largest element of va found using < va2=va.shift(n) Linear right read more..

  • Page - 1186

    Section 40.5.3 Operations 1171 Where the result is a valarray , its length is the same as its valarray operand. If the lengths of the two arrays are not the same, the result of a binary operator on two valarray s is undefined. These valarray operations return new valarray s rather than modifying their operands. This can be expensive, but it doesn’t hav e to be when read more..

  • Page - 1187

    1172 Numerics Chapter 40 combinations of these types. However, an implementation is allowed to convert an operand that is not a valarray to a valarray before performing a required operation. 40.5.4 Slices A slice is an abstraction that allows us to manipulate a one-dimensional array (e.g., a built-in array, a vector, or a valarray ) efficiently as a matrix of arbitrary dimension. read more..

  • Page - 1188

    Section 40.5.4 Slices 1173 or graphically: 00 01 02 03 10 11 12 13 20 21 22 23 0 column 0: 4 8 0 row 0: 123 Row x is described by slice(x ∗4,4,1). That is, the first element of row x is the x ∗4th element of the vector, the next element of the row is the (x ∗4+1)th, etc., and there are 4 elements in each row. For example, slice{0,4,1} describes the first read more..

  • Page - 1189

    1174 Numerics Chapter 40 bool operator!=(const Slice_iter& q ) const { return !( ∗this==q); } bool operator<(const Slice_iter& q) const { return curr<q.curr && s.stride()==q.s.stride() && s.star t()==q.s.star t(); } }; Since a slice has a size, we could even provide range checking. Here, I have taken advantage of slice::size() to provide an end() operation to provide an read more..

  • Page - 1190

    Section 40.5.5 slice_array 1175 slice_array<double> row(va larray<double>& d, int i) { slice_array<double> v = d[slice(0,2,d.size()/2)]; // ... return d[slice(i%2,i,d.size()/2)]; } 40.5.6 Generalized Slices A slice (§29.2.2, §40.5.4) can describe a row or a column of an n -dimensional array. Howev er, sometimes we need to extract a subarray that is not a row or a column. For example, read more..

  • Page - 1191

    1176 Numerics Chapter 40 valarray<siz e_t> lengths {2,3};// 2 elements in the first dimension // 3 elements in the second dimension valarray<siz e_t> strides {3,1}; // 3 is the stride for the first index // 1 is the stride for the second index void f() { gslice s(0,lengths,strides); for (int i=0; i<3; ++i) // for each row for (int j=0; j<2; ++j) // for each element read more..

  • Page - 1192

    Section 40.6 Generalized Numerical Algorithms 1177 Numerical Algorithms (continued) (§iso.26.7) These algorithms take input iterators p=partial_sum(b,e,out) Element i of [out:p) is the sum of elements [b:b+i] p=partial_sum(b,e,out,f) partial_sum using f instead of + p=adjacent_difference(b,e ,out) Element i of [out:p)is ( ∗b+i) ∗(b+i 1) for i>0 ; if e b>0 , then ∗out is ∗b read more..

  • Page - 1193

    1178 Numerics Chapter 40 long price(long val, const Record& r) { return val + r.unit_price ∗ r.number_of_units; } void f(const vector<Record>& v) { cout << "Total value: " << accumulate(v.begin(),v.end(),0,price) << '\n'; } Operations similar to accumulate are called reduce , reduction , and fold in some communities. 40.6.2 inner_product() Accumulating from a sequence is very read more..

  • Page - 1194

    Section 40.6.2 inner_product() 1179 valarray<double> operator ∗(valarray<double>& v, const Matrix& m) { valarray<double> res(m.dim1()); for (siz e_t i = 0; i<m.dim1(); i++) { auto& ci = m.column(i); res[i] = inner_product(ci,ci.end(),&v[0],double(0)); } return res; } Some forms of inner_product are referred to as ‘‘dot product.’’ 40.6.3 partial_sum() and adjacent_difference() The read more..

  • Page - 1195

    1180 Numerics Chapter 40 Given a sequence a , b , c , d , etc., partial_sum() produces a , a+b , a+b+c , a+b+c+d , etc. For example: void f() { partial_sum(temps.begin(),temps.end(),temps.begin()); } Note the way partial_sum() increments res before assigning a new value through it. This allows res to be the same sequence as the input; adjacent_difference() behaves similarly. Thus, read more..

  • Page - 1196

    Section 40.7 Random Numbers 1181 •A random number engine (an engine) is a uniform random number generator that can be created with a default state E{} or with a state determined by a seed E{s} . •A random number engine adaptor (an adaptor) is a random number engine that takes values produced by some other random number engine and applies an algorithm to those values in read more..

  • Page - 1197

    1182 Numerics Chapter 40 Most of the time, most programmers just need a simple uniform distribution of integers or floating- point numbers in a given range. For example: void test() { Rand_int ri {10,20}; // unifor m distr ibution of ints in [10:20) Rand_double rd {0,0.5}; // unifor m distr ibution of doubles in [0:0.5) for (int i=0; i<100; ++i) cout << ri() << ' '; for read more..

  • Page - 1198

    Section 40.7 Random Numbers 1183 // Sample the remaining values in [first+n:last) by selecting a random // number r in the range [0:k], and, if r<n, replace it. // k increases with each iteration, making the probability smaller. // For random access iterators, k = i-first (assuming we increment i and not first). Dist dist; for (Siz ek=n; rst!=last; ++ rst,++k) { Size r = read more..

  • Page - 1199

    1184 Numerics Chapter 40 Standard Random Number Engines (§iso.26.5.3) default_random_engine An alias for an engine with wide applicability and low cost linear_congruential_engine<UI,a,c,m> xi+1 = (axi + c) mod m mersenne_twister_engine<UI,w,n,m,r,a,u,d,s,t,c,l,f> §iso.26.5.3.2 subtract_with_carry_engine<UI,w,s,r> xi+1 = (axi) mod b where b = m r − m s + 1 and a = b − (b − 1) /m The read more..

  • Page - 1200

    Section 40.7.1 Engines 1185 using mt19937_64 = mersenne_twister_engine<uint_fast64_t, 64,312,156, 31,0xb5026f5aa96619e9, 29, 0x5555555555555555, 17, 0x71d67fffeda60000, 37, 0xfff7eee000000000, 43, 6364136223846793005>; using ranlux24_base = subtract_with_carry_engine<uint_fast32_t, 24, 10, 24>; using ranlux48_base = subtract_with_carry_engine<uint_fast64_t, 48, 5, 12>; using ranlux24 = discard_block_engine<ranlux24_base , read more..

  • Page - 1201

    1186 Numerics Chapter 40 Random Number Distribution D (continued) (§iso.26.5.1.6) d.reset() Reset to default state p=d.param() p is d ’s parameters of param_type d.param(p) Reset to the state determined by param_type p x=d(g) x is a value produced by d given the generator g x=d(g,p) x is a value produced by d given the generator g and the parameters p x=d.min() x is the smallest read more..

  • Page - 1202

    Section 40.7.3 Distributions 1187 Bernoulli distributions reflect sequences of tosses of coins with varying degrees of loading: Bernoulli Distributions (§iso.26.5.8.3) Distribution Precondition Defaults Result bernoulli_distribution(p) 0<=p<1 (0.5) {true,false} P(b| p) = ⎧ ⎨ ⎩ p 1 − p if b = true if b = false binomial_distribution<I>(t,p) 0 ≤ p ≤ 1 and 0 ≤ t (1,0.5) [0: ∞) read more..

  • Page - 1203

    1188 Numerics Chapter 40 distributes values symmetrically around a peak (mean) with the distance of elements from the mean being controlled by a standard deviation parameter: Normal Distributions (§iso.26.5.8.5) Distribution Precondition Defaults Result normal_distribution<R>(m,s) 0< s (0.0,1.0) R p(x| μ, σ ) = 1 σ √⎯2π exp ⎛ ⎝ − (x − μ)2 2 σ 2 ⎞ ⎠ read more..

  • Page - 1204

    Section 40.7.3 Distributions 1189 Sampling Distributions (continued) (§iso.26.5.8.6) Distribution Precondition Defaults Result discrete_distribution<I>(lst) discrete_distribution<I>(lst.begin(),lst.end()) discrete_distribution<I>(n,min,max,f) discrete_distribution<I>(b,e) where the i th element of [b:e) is obtained by f(min+i ∗(max?min)/n +(max min)/(2 ∗n)) piecewise_constant_distribution<R>{b,e ,b2,e2} read more..

  • Page - 1205

    1190 Numerics Chapter 40 40.8 Advice [1] Numerical problems are often subtle. If you are not 100% certain about the mathematical aspects of a numerical problem, either take expert advice, experiment, or do both; §29.1. [2] Use variants of numeric types that are appropriate for their use; §40.2. [3] Use numeric_limits to check that the numeric types are adequate for their use; read more..

  • Page - 1206

    41 Concurrency Keep it simple: as simple as possible, but no simpler. – A. Einstein • Introduction • Memory Model Memory Location; Instruction Reordering; Memory Order; Data Races • Atomics atomic Types; Flags and Fences • volatile • Advice 41.1 Introduction Concurrency – the execution of several tasks simultaneously – is widely used to improve through- put (by using several read more..

  • Page - 1207

    1192 Concurrency Chapter 41 •A memory model: a set of guarantees for concurrent access to memory (§41.2) that basically ensures that simple and ordinary access works as one would naively expect • Support for programming without locks: fine-grained low-level mechanisms for avoiding data races (§41.3) •A thread library: a set of components supporting traditional threads-and-locks-style read more..

  • Page - 1208

    Section 41.1 Introduction 1193 thread to another; future s (§5.3.5.1, §42.4.4) can transmit exceptions. Given that concurrent soft- ware is often complex and that code running in different threads is often separately developed, I consider type safety and a standard (preferably exception-based) error-handling strategy even more important than for single-threaded software. The standard-library read more..

  • Page - 1209

    1194 Concurrency Chapter 41 happen if a linker allocated c and b in the same word in memory and (like most modern hardware) the machine could not load or store anything smaller than a word: c b word: Without a well-defined and reasonable memory model, thread 1 might read the word containing b and c , change c , and write the word back into memory. At the same time, read more..

  • Page - 1210

    Section 41.2.2 Instruction Reordering 1195 41.2.2 Instruction Reordering To gain performance, compilers, optimizers, and hardware reorder instructions. Consider: // thread 1: int x; bool x_init; void init() { x = initializ e(); // no use of x_init in initialize() x_init = true; // ... } For this piece of code there is no stated reason to assign to x before assigning to x_init . The read more..

  • Page - 1211

    1196 Concurrency Chapter 41 opportunities for confusion as different threads look at a value at different times and in different places in the memory hierarchy. For example, my simplified description mentions only a single cache; many popular architectures use a three-level cache. To illustrate, here is a diagram of a pos- sible two-level cache architecture where each core has read more..

  • Page - 1212

    Section 41.2.4 Data Races 1197 41.2.4 Data Races From these examples, every sensible person will conclude that we have to be very careful when programming threads. But how? First, we must avoid data races. Two threads have a data race if both can access a memory location (as defined in §41.2.1) simultaneously and at least one of their accesses is a write. Note that defining read more..

  • Page - 1213

    1198 Concurrency Chapter 41 That would have sav ed a lot of work for the committee and for some programmers. How- ev er, this idea was effectively vetoed by the providers of operating systems and virtual machines: they insisted that they needed roughly what was then provided by the various C++ implementations – what is now provided by the C++ standard. The read more..

  • Page - 1214

    Section 41.3 Atomics 1199 consume operation, an acquire operation, a release operation, or both an acquire and release opera- tion (§iso.1.10). • For an acquire operation, other processors will see its effect before any subsequent opera- tion’s effect. • For a release operation, other processors will see every preceding operation’s effect before the effect of the operation itself. read more..

  • Page - 1215

    1200 Concurrency Chapter 41 For explanations, see the specialist literature, for example, [Boehm,2008] and [Williams,2012]. It is entirely architecture-specific whether a given memory order makes sense. Clearly, a relaxed memory model is not something to be directly used in applications programming. Utilizing a relaxed memory model is an even more specialized task than general lock-free read more..

  • Page - 1216

    Section 41.3.1 atomic Types 1201 atomic<T> (continued) (§iso.29.5) x.val represents the value of the atomic x ; all operations are noexcept x=t Assignment of T : x.val=t t=x Implicit conversion to T : t=x.val x.is_lock_free() Are operations on x lock free? x.store(t) x.val=t x.store(t,order) x.val=t ; memory order is order t=x.load() t=x.val t=x.load(order) t=x.val ; memory order is order read more..

  • Page - 1217

    1202 Concurrency Chapter 41 ˜shared_ptr() { if ( ∗puc) delete p; } private: T ∗ p; // pointer to shared object atomic<int> ∗ puc; // pointer to use count }; Here, ∗puc is an atomic (allocated somewhere by a shared_ptr constructor), so that the decrement operation ( ) is atomic and the new value is correctly reported in the thread destroying a shared_ptr . The first read more..

  • Page - 1218

    Section 41.3.1 atomic Types 1203 This is a simplified version of code that would insert data at the right position in an ordered linked list. I read the head , use it as the next of my new Link , and then write the pointer to my new Link to head . I do that repeatedly until no other thread has managed to change the head while I was getting nh ready. Let us read more..

  • Page - 1219

    1204 Concurrency Chapter 41 Xx; // we need a lock to initialize an X mutex lx; // the mutex to be used to lock x dur ing initialization atomic<bool> x_init {false}; // an atomic used to minimize locking void some_code() { if (!x_init) { // proceed if x is uninitialized lx.lock(); if (!x_init) { // proceed if x is still uninitialized // ... initialize x ... x_init = read more..

  • Page - 1220

    Section 41.3.1 atomic Types 1205 atomic_ ∗ operations (continued) (§iso.29.6.5) All operations are noexcept atomic_store(p,v) Store v in ∗p x=atomic_load(p) Assign ∗p to x x=atomic_load(p) Load ∗p into x b=atomic_compare_exchang e_weak(p,q,v) Compare and exchange ∗p and ∗q; b=( ∗q==v) ... about 70 more functions ... 41.3.2 Flags and Fences In addition to the support for atomic types, the read more..

  • Page - 1221

    1206 Concurrency Chapter 41 Using {} to initialize atomic_ ag seems to make sense. However, there is no guarantee that 0 represents clear. A machine where clear is 1 is rumored to exist. Clearing using AT OMIC_FLAG_INIT is the only portable and reliable way of initializing an atomic_ ag. The AT OMIC_FLAG_INIT is an implementation-supplied macro. You can think of an atomic_ ag read more..

  • Page - 1222

    Section 41.4 volatile 1207 Do not assume that volatile has special meaning in the memory model. It does not. It is not – as in some later languages – a synchronization mechanism. To get synchronization, use an atomic (§41.3), a mutex (§42.3.1), or a condition_variable (§42.3.4). 41.5 Advice [1] Use concurrency to improve responsiveness or to improve throughput; §41.1. [2] Work at read more..

  • Page - 1223

    This page intentionally left blank read more..

  • Page - 1224

    42 Threads and Tasks Keep Calm and Carry On. – English slogan • Introduction • Threads Identity; Construction; Destruction; join() ; detach() ; Namespace this_thread ; Killing a thread ; thread_local Data • Avoiding Data Races Mutexes; Multiple Locks; call_once() ; Condition Variables • Task-Based Concurrency future and promise ; promise ; packaged_task ; future ; shared_future ; async() ; A read more..

  • Page - 1225

    1210 Threads and Tasks Chapter 42 42.2 Threads A thread is an abstraction of the computer hardware’s notion of a computation. The C++ standard- library thread s are intended to map one-to-one with the operating system’s threads. We use thread s when several tasks in a program need to progress concurrently. On a system with several process- ing units (‘‘cores’’), thread s read more..

  • Page - 1226

    Section 42.2 Threads 1211 thread system thread Consequently, a thread can be moved but not copied. After being the source of a move, a thread no longer represents a thread of computation. In par- ticular, it cannot be join() ed. The thread::hardware_concurrency() operation reports the number of tasks that can simultane- ously proceed with hardware support. The exact meaning of that is read more..

  • Page - 1227

    1212 Threads and Tasks Chapter 42 42.2.2 Construction A thread constructor takes a task to be executed and the arguments required by that task. The num- ber and types of arguments must match what the task requires. For example: void f0(); // no arguments void f1(int); // one int argument thread t1 {f0}; thread t2 {f0,1}; // error : too many arguments thread t3 {f1}; // error read more..

  • Page - 1228

    Section 42.2.2 Construction 1213 The thread constructors are variadic templates (§28.6). This implies that to pass a reference to a thread constructor, we must use a reference wrapper (§33.5.1). For example: void my_task(vector<double>& arg); void test(vector<double>& v) { thread my_thread1 {my_task,v}; // oops: pass a copy of v thread my_thread2 {my_task,ref(v)}; // OK: pass v read more..

  • Page - 1229

    1214 Threads and Tasks Chapter 42 42.2.4 join() A t.join() tells the current thread not to proceed until t completes. For example: void tick(int n) { for (int i=0; i!=n; ++i) { this_thread::sleep_for(second{1}); // §42.2.6 output("Alive!"); } } int main() { thread timer {tick,10}; timer.join(); } This will output Alive! ten times at about 1-second intervals. Had the timer.join() been read more..

  • Page - 1230

    Section 42.2.4 join() 1215 struct guarded_thread : thread { using thread::thread; // §20.3.5.1 ˜guarded_thread() { if (t.joinable()) t.join(); } }; Unfortunately, guarded_thread is not a standard-library class, but in the best RAII tradition guarded_thread makes our code shorter and less error-prone. For example: void run2(int i, int n) // simple use of a guard { guarded_thread t1 {f}; guarded_thread read more..

  • Page - 1231

    1216 Threads and Tasks Chapter 42 Unless I go beyond the standard library (e.g., using get_native_handle() and ‘‘native’’ system facili- ties), I cannot do so for detached threads. Also, how do I debug a system where the behavior of detached threads cannot be directly observed? What happens if a detached thread holds a pointer to something in the scope in which it was read more..

  • Page - 1232

    Section 42.2.5 detach() 1217 easy (and almost invisible) to create a pointer to a local variable: [&] . Fortunately, we hav e to say detach() to allow a thread to exit its scope; don’t do that without a very good reason, and then only after carefully considering what its task might do. 42.2.6 Namespace this_thread Operations for the current thread are found in namespace read more..

  • Page - 1233

    1218 Threads and Tasks Chapter 42 If needed, application programmers can write their own versions of this idea. For example, many tasks involve a request loop. In that case, a ‘‘kindly commit suicide’’ message would allow the receiving thread to release all resources and then terminate. If there is no request loop, a task could periodically examine a ‘‘needed’’ variable read more..

  • Page - 1234

    Section 42.2.8 thread_local Data 1219 One-per-class (static) values used to be popular. They include default values, use counters, caches, free lists, answers to frequently asked questions, and many obscure uses. When used in a concurrent system, we have a classic problem: // somewhere in thread 1: Map<string,int>::set_default("Heraclides",1); // somewhere in thread 2: read more..

  • Page - 1235

    1220 Threads and Tasks Chapter 42 Strictly speaking, condition variables do not prevent data races. Rather, they sav e us from having to introduce shared data that might become a source of data races. 42.3.1 Mutexes A mutex is an object used to represent exclusive access to some resource. Thus, it can be used to protect against data races and to synchronize access to read more..

  • Page - 1236

    Section 42.3.1 Mutexes 1221 cout_mutex.lock(); cout << "Fro m thread " << name << " : " << a1 << a2 << a3; cout_mutex.unlock(); } If all thread s use write() we should get output from different thread s properly separated. The snag is that every thread has to use a mutex as intended. The correspondence between a mutex and its resource is read more..

  • Page - 1237

    1222 Threads and Tasks Chapter 42 void world() { cout_mutex.lock(); cout << "World!"; cout_mutex.unlock(); } int main() { thread t1 {hello}; thread t2 {world}; t1.join(); t2.join(); } Given that, we will get the output Hello, World! or World! Hello, We will not get cout corrupted or some mixed-up output characters. The try_lock() operation is used when we have some other work read more..

  • Page - 1238

    Section 42.3.1.1 mutex and recursive_mutex 1223 When using locks, we have to bew are of deadlock. That is, we must not wait for a lock that can never be released. The simplest form of deadlock requires only one lock and one thread . Consider a variant of the thread-safe output operation: template<typename Arg, typename... Args> void write(Arg a, Args tail...) { cout_mutex.lock(); read more..

  • Page - 1239

    1224 Threads and Tasks Chapter 42 mutex mtx; try { mtx.lock(); mtx.lock(); // tr y to lock a second time } catch (system_error& e) { mtx.unlock(); cout << e.what() << '\n'; cout << e.code() << '\n'; } I got the output device or resource busy generic: 16 This looks like a good argument for using a lock_guard or a unique_lock (§42.3.1.4). 42.3.1.3 timed_mutex and read more..

  • Page - 1240

    Section 42.3.1.3 timed_mutex and recursive_timed_mutex 1225 void next() { while (true) { Image next_image; // ... compute ... if (imtx.try_lock(milliseconds{100})) { buf=next_image; imtx.unlock(); } } } The assumption here is that if the image cannot be updated reasonably fast (here, in 100 millisec- onds), the user would prefer a newer version of the image. Further, it is assumed that read more..

  • Page - 1241

    1226 Threads and Tasks Chapter 42 void use(mutex& mtx, vector<string>& vs, int i) { lock_guard<mutex> g {mtx}; if (i<0) return; string s = vs[i]; // ... } The lock_guard ’s destructor does the necessary unlock() on its argument. As usual, we should only hold a lock for the minimal amount of time, so a lock_guard should not become an excuse for holding a lock until the read more..

  • Page - 1242

    Section 42.3.1.4 lock_guard and unique_lock 1227 Such an object is called a lockable object. The obvious lockable object is of a standard-library mutex type, but users can define their own. A lock_guard is a very simple class with no interesting operations. All it does is RAII for a mutex . To get an object that provides RAII and operations on a contained mutex , we use a read more..

  • Page - 1243

    1228 Threads and Tasks Chapter 42 mutex mtx; timed_mutex mtx2; void use() { unique_lock<defer_lock_t,mutex> lck {mtx}; unique_lock<defer_lock_t,timed_mutex> lck2 {mtx2}; lck.tr y_lock_for(milliseconds{2}); // error : mutex does not have member try_lock_for() lck2.tr y_lock_for(milliseconds{2}); // OK lck2.tr y_lock_until(steady_clock::now()+milliseconds{2}); // ... } If you give a duration or a time_point read more..

  • Page - 1244

    Section 42.3.2 Multiple Locks 1229 thread t1 {task,ref(mtx1),ref(mtx2)}; thread t2 {task,ref(mtx2),ref(mtx1)}; The ref() is the std::ref() reference wrapper from <functional> (§33.5). It is needed to pass a refer- ence through a variadic template (the thread constructor; §42.2.2). A mutex cannot be copied or moved, so I must pass them by reference (or use a pointer). Change the names read more..

  • Page - 1245

    1230 Threads and Tasks Chapter 42 42.3.3 call_once() We often want to initialize an object without getting into a race condition. The type once_ ag and the function call_once() offer a low-level, efficient, and simple tool for that. call_once (§iso.30.4.2) once_ ag {}; Default constructor: has not been used call_once( ,f,args) Call f(args) if hasn’t yet been used For example: class X read more..

  • Page - 1246

    Section 42.3.4 Condition Variables 1231 42.3.4 Condition Variables Condition variables are used to manage communication among thread s. A thread can wait (block) on a condition_variable until some event, such as reaching a specific time or another thread complet- ing, occurs. condition_variable (§iso.30.5) lck must be a unique_lock<mutex> condition_variable cv {}; Default constructor: throw a read more..

  • Page - 1247

    1232 Threads and Tasks Chapter 42 Apparently, allowing spurious wake-up simplifies implementation of condition_variable s on some systems. Always use ‘‘plain’’ wait() in a loop. For example: while (queue.empty()) wait(queue_lck); An additional reason for this loop is that some thread may have ‘‘snuck up’’ and invalidated the condition (here, queue.empty() ) before the thread calling read more..

  • Page - 1248

    Section 42.3.4 Condition Variables 1233 notify_one() to wake a possibly blocked consumer, and implicitly releases the mutex . I provided an rvalue version of put() so that we can transmit objects of types that have move, but not copy, opera- tions, such as unique_ptr (§5.2.1, §34.3.1) and packaged_task (§42.4.3). I used notify_one() rather than notify_all() because I only added one read more..

  • Page - 1249

    1234 Threads and Tasks Chapter 42 thread t1 {producer}; thread t2 {consumer}; Using a condition_variable saves a consumer the bother of explicitly dealing with the case where it runs out of work to do. Had we simply used a mutex to control access to the Sync_queue , the con- sumer would have had to repeatedly wake up, look for work on the queue, and decide what to do read more..

  • Page - 1250

    Section 42.3.4 Condition Variables 1235 The roughly equivalent modification to put() would be to wait for the consumer to make inroads into a long queue, but not for too long a time: template<typename T> void Sync_queue::put(T val, steady_clock::duration d, int n) { unique_lock<mutex> lck(mtx); bool not_full = cond.wait_for(lck,d,[this]{ return q.size()<n; }); if (not_full) { read more..

  • Page - 1251

    1236 Threads and Tasks Chapter 42 To support this task-based model of concurrency, the standard library offers: Task Support (§iso.30.6.1) packaged_task<F> Package a callable object of type F to be run as a task promise<T> A type of object to which to put one result of type T future<T> A type of object from which to move one result of type T read more..

  • Page - 1252

    Section 42.4.1 future and promise 1237 the return value or exception, it contains the information needed for two thread s to safely exchange the information. At a minimum, a shared state must be able to hold: •A value of the appropriate type or an exception. For a future ‘‘returning void ’’ the value is nothing. •A ready bit to indicate whether a value or exception read more..

  • Page - 1253

    1238 Threads and Tasks Chapter 42 promise<T> (continued) (§iso.30.6.5) pr.set_value_at_thread_exit(x) The result of the task is the value x ; don’t make the result ready until thread exit pr.set_exception_at_thread_exit(p) The result of the task is the exception pointed to by p ; p is an exception_ptr ; don’t make the result ready until thread exit swap(pr,pr2) pr.swap(pr2) ; noexcept read more..

  • Page - 1254

    Section 42.4.3 packaged_task 1239 packaged_task<R(ArgTypes...)> (§iso.30.6.9) packaged_task pt {}; Default constructor: pt holds no task; noexcept packaged_task pt {f}; Construct pt holding f ; f is moved into pt ; use the default allocator; explicit packaged_task pt {allocator_arg_t,a,f}; Construct pt holding f ; f is moved into pt ; use allocator a ; explicit packaged_task pt {pt2}; Move read more..

  • Page - 1255

    1240 Threads and Tasks Chapter 42 packaged_task<int(int)> pt1 {ff}; // store ff in pt1 packaged_task<int(int)> pt2 {ff}; // store ff in pt2 pt1(1); // let pt1 call ff(1); pt2(0); // let pt2 call ff(0); So far, nothing appears to have happened. In particular, we don’t see the exception triggered by ff(0) . In fact, pt1(1) did a set_value(1) on the promise attached to pt1 read more..

  • Page - 1256

    Section 42.4.3 packaged_task 1241 using PTT = Res(Args); Sync_queue<packaged_task<PTT>> server; Res f(Args); // function: do something struct G { Res operator()(Args); // function object: do something // ... }; auto h = [=](Args a) { /* do something */ }; // lambda packaged_task<PTT> job1(f); packaged_task<PTT> job2(G{}); packaged_task<PTT> job3(h); auto f1 = job1.get_future(); auto f2 read more..

  • Page - 1257

    1242 Threads and Tasks Chapter 42 future<T> (continued) (§iso.30.6.6) sf=fu.share() Move fu ’s value into a shared_future sf ; fu no longer has a shared state x=fu.get() fu ’s value is moved into x ; if an exception was stored in fu , throw it; fu no longer has a shared state; don’t try to get() twice fu.get() For future<void> : like x=fu.get() , but don’t read more..

  • Page - 1258

    Section 42.4.4 future 1243 I can easily implement a version of wait_for_all() : template<typename T> vector<T> wait_f or_all(vector<future<T>>& vf) { vector<T> res; for (auto& fu : vf) res.push_back(fu.g et()); return res; } That’s easy enough to use, but it has a flaw: if I wait for ten future s, I risk my thread getting blocked ten times. Ideally, my thread would read more..

  • Page - 1259

    1244 Threads and Tasks Chapter 42 Like the implementation of wait_for_all() , this implementation has a flaw: ideally, the caller of wait_for_any() should never hav e to wake up just to find that no tasks had completed and should be unblocked immediately when one does. This simple implementation only approximates that. With a large d a useless wake-up is unlikely but implies read more..

  • Page - 1260

    Section 42.4.6 async() 1245 42.4.6 async() Given future and promise (§42.4.1) and packaged_task (§42.4.3), we can write simple tasks without worrying too much about thread s. Given those, a thread is just something you give a task to run. However, we still need to consider how many thread s to use and whether a task is best run on the current thread or on another. Such decisions can read more..

  • Page - 1261

    1246 Threads and Tasks Chapter 42 By a ‘‘recycled thread ’’ I mean a thread from a collection of thread s (a thread pool) that async() may create once and use over and over to execute a variety of tasks. Depending on the implementa- tion of system threads, this can drastically lower the cost of executing a task on a thread .If a thread is recycled, the read more..

  • Page - 1262

    Section 42.4.7 A Parallel nd() Example 1247 An individual (sequential) task is simply a use of the standard-library nd_if() : template<typename Pred> Record ∗ nd_rec(vector<Record>& vr, int rst, int last, Pred pr) { vector<Record>::iterator p = std:: nd_if(vr.begin()+ rst,vr.begin()+last,pr); if (p == vr.begin()+last) return nullptr; // at end: no record found return & ∗p; // read more..

  • Page - 1263

    1248 Threads and Tasks Chapter 42 This first version of a parallel nd() first spawns a lot of tasks and then proceeds to wait for them in order. Like std:: nd_if() , it reports the first element that matches the predicate; that is, it finds the element with the lowest index that matches. That may be fine, but: • We could end up waiting for a lot of tasks that read more..

  • Page - 1264

    Section 42.4.7 A Parallel nd() Example 1249 template<typename Pred> vector<Record ∗> nd_all_rec(vector<Record>& vr, int rst, int last, Pred pr) { vector<Record ∗> res; for (int i= rst; i!=last; ++i) if (pr(vr[i])) res.push_back(&vr[i]); return res; } This nd_all_rec() is arguably simpler than the original nd_rec() . Now we just need to launch nd_all_rec() a suitable number read more..

  • Page - 1265

    1250 Threads and Tasks Chapter 42 Finally, we must consider if the effort to parallelize was worthwhile. To do so, I added simple sequential versions to my test: void just_ nd_cheap_red() { auto p = nd_if(goods.begin(),goods.end(), [](Record& r) { return r.price<200 && r.color==Color::red; }); if (p!=goods.end()) cout << "recor d "<< ∗p << '\n'; else cout read more..

  • Page - 1266

    Section 42.5 Advice 1251 [13] Use packaged_task s to handle exceptions thrown by tasks and to arrange for value return; §42.4.3. [14] Use a packaged_task and a future to express a request to an external service and wait for its response; §42.4.3. [15] Don’t get() twice from a future ; §42.4.4. [16] Use async() to launch simple tasks; §42.4.6. [17] Picking a good granularity of read more..

  • Page - 1267

    This page intentionally left blank read more..

  • Page - 1268

    43 The C Standard Library C is a strongly typed, weakly checked language. – D. M. Ritchie • Introduction • Files • The prinf() Family • C-Style Strings • Memory • Date and Time • Etc. • Advice 43.1 Introduction The standard library for the C language is with very minor modifications incorporated into the C++ standard library. The C standard library provides quite a few read more..

  • Page - 1269

    1254 The C Standard Library Chapter 43 File Open and Close f=fopen(s,m) Open a file stream for a file named s with the mode m f is the FILE ∗ for the opened file if successful or nullptr x=fclose(f) Close file stream f ; return 0 if successful A file opened with fopen() must be closed by fclose() or the file will remain open until the operating system closes it. If read more..

  • Page - 1270

    Section 43.3 The printf() Family 1255 conversion specifications, such as %c (print as character) and %d (print as decimal integer), in the format string. For example: int x = 5; const char ∗ p = "Pedersen"; printf("the value of x is '%d' and the value of s is '%s'\n",x,s); A character following a % controls the handling of an argument. The first % applies to read more..

  • Page - 1271

    1256 The C Standard Library Chapter 43 ll an optional pair of characters ll (ell ell), specifying that a following d , i , o , u , x ,or X corre- sponds to a (signed or unsigned) long long integer argument; L an optional character L , specifying that a following a , A , e , E , f , F , g ,or G corresponds to a long double argument; j specifying that a following d , read more..

  • Page - 1272

    Section 43.3 The printf() Family 1257 In no case does a nonexistent or small field width cause truncation of a field; padding takes place only if the specified field width exceeds the actual width. Here is a more elaborate example: char ∗ line_format = "#line %d \"%s\"\n"; int line = 13; char ∗ le_name = "C++/main.c"; printf("int a;\n"); read more..

  • Page - 1273

    1258 The C Standard Library Chapter 43 strongly recommend against the use of scanf() . So what can we do for input if we are obliged to use stdio? One popular answer is ‘‘use the standard-library function gets() ’’: // very dangerous code: char s[buf_siz e]; char ∗ p = gets(s); // read a line into s The call p=gets(s) reads characters into s until a newline or an read more..

  • Page - 1274

    Section 43.4 C-Style Strings 1259 C-Style String Operations x=strlen(s) Count the characters (excluding the terminating 0 ) p=strcpy(s,s2) Copy s2 into s ;[s:s+n) and [s2:s2+n) may not overlap; p=s ; the terminating 0 is copied p=strcat(s,s2) Copy s2 onto the end of s ; p=s ; the terminating 0 is copied x=strcmp(s, s2) Compare lexicographically: if s<s2 , then x is negative; if s==s2 , read more..

  • Page - 1275

    1260 The C Standard Library Chapter 43 C-Style Memory Operations q=memcpy(p,p2,n) Copy n bytes from p2 to p (like strcpy ); [p:p+n) and [p2:p2+n) may not overlap; q=p q=memmove(p,p2,n) Copy n bytes from p2 to p ; q=p x=memcmp(p,p2,n) Compare n bytes from p2 to the equivalent n bytes from p ; x<0 means < , x==0 means == , 0<x means > q=memchr(p,c,n) Find c (converted to an read more..

  • Page - 1276

    Section 43.5 Memory 1261 Most uses of realloc() are better done using a vector (§31.4.1). The mem ∗ functions are found in <cstring> and the allocation functions in <cstdlib> . 43.6 Date and Time In <ctime> , you can find several types and functions related to date and time: Date and Time Types clock_t An arithmetic type for holding short time intervals (maybe read more..

  • Page - 1277

    1262 The C Standard Library Chapter 43 A example of the result of a call of asctime() is "Sun Sep 16 01:03:52 1973\n" Here is an example of how clock() can be used to time a function: int main(int argc, char ∗ argv[]) { int n = atoi(argv[1]); clock_t t1 = clock(); if (t1 == clock_t( 1)) { // clock_t(-1) means "clock() didn’t wor k" cerr << "sorry , read more..

  • Page - 1278

    Section 43.6 Date and Time 1263 Date and Time Formatting %a Abbreviated weekday name %A Full weekday name %b Abbreviated month name %B Full month name %c Date and time representation %C The year divided by 100 and truncated to a decimal integer [00:99] %d The day of the month as a decimal number [01:31] %D Equivalent to %m/%d/%y %e The day of the month as a decimal number read more..

  • Page - 1279

    1264 The C Standard Library Chapter 43 Some conversion specifiers can be modified by an E or O modifier, indicating alternative imple- mentation-specific and locale-specific formatting. For example: Date and Time Format Modifier Examples %Ec The locale’s alternative date and time representation %EC The name of the base year (period) in the locale’s alternative representation %OH read more..

  • Page - 1280

    Section 43.7 Etc. 1265 For more C standard library functions see [Kernighan,1988] or some other reputable C language reference. In <cstdint> ,wefind int_fast16_t and other standard integer aliases: Integer Type Aliases N can be 8 , 16 , 32 ,or 64 int_ N_t Integer type of N bytes, e.g. int_8_t uint_ N_t Unsigned integer type of N bytes, e.g., uint_16_t int_least N_t Integer type of read more..

  • Page - 1281

    This page intentionally left blank read more..

  • Page - 1282

    44 Compatibility You go ahead and follow your customs, and I´ll follow mine. – C. Napier • Introduction • C++11 Extensions Language Features; Standard-Library Components; Deprecated Features; Coping with Older C++ Implementations • C/C++ Compatibility C and C++ Are Siblings; ‘‘Silent’’ Differences; C Code That Is Not C++; C++ Code That Is Not C • Advice 44.1 Introduction This read more..

  • Page - 1283

    1268 Compatibility Chapter 44 complete and helpful implementation. For delivering a product, a more conservative strategy might be in order to maximize the number of systems on which the product can run. In the past, this has been a reason (and more often just an excuse) to avoid C++ features deemed novel. However, implementations are converging, so the need for portability read more..

  • Page - 1284

    Section 44.2.1 Language Features 1269 [26] Testing for the possibility of a throw in an expression: the noexcept operator (§13.5.1.1) [27] C99 features: extended integral types (i.e., rules for optional longer integer types; §6.2.4); concatenation of narrow/wide strings; __func__ and __STDC_HOSTED__ (§12.6.2); _Pragma(X) (§12.6.3); v ararg macros and empty macro arguments (§12.6) [28] inline read more..

  • Page - 1285

    1270 Compatibility Chapter 44 [15] emplace() operations for containers (§31.3.6) [16] Wide use of constexpr functions [17] Systematic use of noexcept functions [18] Improved function adaptors: function and bind() (§33.5) [19] string to numeric value conversions (§36.3.5) [20] Scoped allocators (§34.4.4) [21] Type traits, such as is_integral and is_base_of (§35.4) [22] Time utilities: duration and read more..

  • Page - 1286

    Section 44.2.3 Deprecated Features 1271 C-style casts should have been deprecated when the named casts (§11.5.2) were introduced. Programmers should seriously consider banning C-style casts from their own programs. Where explicit type conversion is necessary, static_cast , reinterpret_cast , const_cast , or a combination of these can do what a C-style cast can. The named casts should be read more..

  • Page - 1287

    1272 Compatibility Chapter 44 44.3.1 C and C++ Are Siblings Classic C has two main descendants: ISO C and ISO C++. Over the years, these languages have ev olved at different paces and in different directions. One result of this is that each language pro- vides support for traditional C-style programming in slightly different ways. The resulting incom- patibilities can make life read more..

  • Page - 1288

    Section 44.3.1 C and C++ Are Siblings 1273 C++98 C99 C89 C++11 C11 The areas are not to scale. Both C++11 and C11 have most of K&R C as a subset. C++11 has most of C11 as a subset. There are features belonging to most of the distinct areas. For example: C89 only Call of undeclared function C99 only Variable-length arrays (VLAs) C++ only Templates C89 and C99 Algol-style read more..

  • Page - 1289

    1274 Compatibility Chapter 44 int x[99]; void f() { struct x { int a; }; sizeof(x); /* size of the array in C, size of the struct in C++ */ sizeof(struct x); /* size of the struct */ } 44.3.3 C Code That Is Not C++ The C/C++ incompatibilities that cause most real problems are not subtle. Most are easily caught by compilers. This section gives examples of C code that read more..

  • Page - 1290

    Section 44.3.3 C Code That Is Not C++ 1275 struct S { int x,y; } f(); /* C; not C++ */ void g(struct S { int x,y; } y); /* C; not C++ */ The C++ rules for defining types make such declarations useless, and they are not allowed. • In C, integers can be assigned to variables of enumeration type: enum Direction { up, down }; enum Direction d = 1; /* error : int read more..

  • Page - 1291

    1276 Compatibility Chapter 44 char ch; void ∗ pv = &ch; int ∗ pi = pv; // not C++ ∗pi = 666; // overwr ite ch and other bytes near ch If you use both languages, cast the result of malloc() to the right type. If you use only C++, avoid malloc() . • In C, the type of a string literal is ‘‘array of char ,’’ but in C++ it is ‘‘array of const char read more..

  • Page - 1292

    Section 44.3.3.1 ‘‘Classic C’ ’ Problems 1277 44.3.3.1 ‘‘Classic C’ ’ Problems Should you need to upgrade Classic C programs (‘‘K&R C’’) or C89 programs, a few more prob- lems will emerge: • C89 does not have the // comments (though most C89 compilers added them): int x; // not C89 • In C89, the type specifier defaults to int (known as ‘‘implicit int read more..

  • Page - 1293

    1278 Compatibility Chapter 44 [4] const (§7.5, §7.5); partially added to C [5] The Boolean type bool (§6.2.2); partially added to C99 [6] Named casts (§11.5.2) • Facilities for user-defined types: [1] Classes (Chapter 16) [2] Member functions (§16.2.1) and member classes (§16.2.13) [3] Constructors and destructors (§16.2.5, Chapter 17) [4] Derived classes (Chapter 20, Chapter 21) [5] virtual functions read more..

  • Page - 1294

    Section 44.4 Advice 1279 44.4 Advice [1] Before using a new feature in production code, try it out by writing small programs to test the standards conformance and performance of the implementations you plan to use; §44.1. [2] For learning C++, use the most up-to-date and complete implementation of Standard C++ that you can get access to; §44.2.4. [3] The common subset of C read more..

  • Page - 1295

    This page intentionally left blank read more..

  • Page - 1296

    I Index Knowledge is of two kinds. We know a subject ourselves, or we know where we can find information on it. – Samuel Johnson Token ! logical not operator 274 logical_not 966 not 258 valarray 1170 != bitset 980 container 902 duration 1012 error_categor y 877 error_code 875 iterator 959 match_results 1060 not-equal operator 41 not_eq 258 not_equal_to 966 pair 984 regex_iterator 1067 read more..

  • Page - 1297

    1282 Index I duration 1012 format character 1255 modulus 966 modulus operator 40 remainder operator 40 valarray 1170 %= duration 1011 operator 42 valarray 1167 & address-of operator 45, 172 and 258 bitset 979 bitwise and operator 274 predefined 531 prohibiting 531 reference to 45, 190 valarray 1170 && bitand 258 logical and operator 260, 274 logical_and 966 no order 531 rvalue reference 75, 194 read more..

  • Page - 1298

    – Token – Index 1283 atomic<T> 1203 decrement operator 42, 276 duration 1011 for pointer 181 iterator 959 user-defined operator 554 -= atomic<T> 1203 duration 1011 iterator operator 244 time_point 1014 valarray 1167 -> dereference operator 552 iterator 959 member access operator 202 operator 466 regex_iterator 1067 regex_token_iterator 1068 required 758 return type 308 unique_ptr 987 user-defined read more..

  • Page - 1299

    1284 Index I pair 984 shared_ptr 992 string 1040 sub_match 1058 time_point 1014 tuple 985 unique_ptr 987 valarray 1170 <> specialization 682 template 731, 737 = 0 65, 598 and == 41 and ==, equivalence 510 atomic<T> 1200 auto 42 container 896 default 518, 524 delete 524 delete vs. missing 525 duration 1010 future 1241 independence 510 initialization problem 492 initializer 41 match_results 1060 Matrix 832 read more..

  • Page - 1300

    – Token – Index 1285 bitset 979 valarray 1167 ? :, arithmetic-if 275 regex 1052 ?: conditional expression 264, 275 operator 275 [, regex 1052 [&], lambda 294 [=], lambda 294 [] , and 183 −> and ∗ and 553 array 976 array of 44 bitset 979 container 900 design of 562 iterator lambda 294 map 910 match_results 1060 Matrix 833 string 1041 subscript operator 50 subscript operator 174 valarray read more..

  • Page - 1301

    1286 Index I A \a, alert 143 a, file mode 1254 %a format 1256 %A format 1256 ABA problem 1202 ABI and layout 211 abor t() 372, 443 abs() 1163–1164 <cstdlib> 865 valarray 1170 absence of initializer 161 abstract base class 598 class 598 class 65 class and design 617 class constructor 598 class destructor 598 class, use of 622 type 65 abstraction data 11 elegant and efficient 9 mechanisms read more..

  • Page - 1302

    – A – Index 1287 alignas, alignment 151 aligned_storage 1025 aligned_union 1025 alignment 151, 203 alignas 151 alignof 151 alignment_of 1022 alignof, alignment 151 all, catch 370 allocate array 281 allocate() allocator 997 allocator_traits 998 allocateshared(), shared_ptr 992 allocation 63 and deallocation 277, 556 unit of 172 allocator 995 scoped 1000 allocator allocate() 997 construct() 997 constructor 997 read more..

  • Page - 1303

    1288 Index I reference 266 argv argc, main() 253 arithmetic conversions, usual 258, 271 Matrix 836 mixed-mode 536 operation 966 operator 40 pointer 181, 276 ratio compile-time 1017 type 139 vector 131, 1166 arithmetic-if ?: 275 ARM 25 array 174 aggregate 202 allocate 281 argument 318–319 array of 183 array vs. 976 assignment 180 associative 550 by string, initialization of 176 deallocate 281 read more..

  • Page - 1304

    – A – Index 1289 atan2() 1163 valarray 1170 atexit() and destructor 444 and exception 352 atomic operation 1196, 1198 atomic type 1200 <atomic> 865 atomic_compare_exchange_weak() 1204 atomic_flag AT OMIC_FLAG_INIT 1205 clear() 1205 test_and_set() 1205 AT OMIC_FLAG_INIT, atomic_flag 1205 atomic_init() 1204 atomic_is_lock_free( 1204 atomic_load() 1204 atomic_signal_fence(), fence 1206 atomic_store() 1204 atomic<T read more..

  • Page - 1305

    1290 Index I basic_string<char32_t>, u32string 887 basic_string<wchar_t>, wstring 887 before/after 483 begin() 99, 103, 954 iterator 899 match_results 1060 nonmember 964 string 1044 unordered_map 920 valarray 1170 beginner, book for 37 behavior, undefined 136 Bell Laboratories, AT&T 25 benefits, template 721 Bernoulli distributions 1187 bernoulli_distribution 1187 Bessel 1164 beta() 1164 bibliography 32 read more..

  • Page - 1306

    – B – Index 1291 book for beginner 37 organization of 4 structure of 4 _Bool 1278 bool 40, 139 conversion to 269 error_code to 875 hash of 915 nullptr 140 promotion 267 shared_ptr conversion to 992 unique_lock 1227 unique_ptr conversion to 987 bottom-up construction 486 branch, declaration on 229 break 231, 236, 244, 252 case and 230 statement 252 broken_promise 883 bucket load 919 unordered_map read more..

  • Page - 1307

    1292 Index I C++0x 23, 27 C++98 28 facilities, use of 8 language features 28 standard library 29 C++98 25 C++11 28 language features 26 standard library 26 C11 1271 C89 and C99 14, 1271 C99, C89 and 14, 1271 cache memory 1193 cache example 462 calculator example 242, 399–400, 431 call (), function 315 by reference 191, 316 by value 316 function 315 of constructor 487 of destructor 487 of read more..

  • Page - 1308

    – C – Index 1293 set, larger 178 special 143 string 864 thousands_sep() separator 1129 traits 1035 type 140, 1035 type char 141 CHAR_BIT 1162 char_traits 1035 assign() 1035 char_type 1035 compare() 1035 copy() 1035 eof() 1035 eq() 1035 eq_int_type() 1035 find() 1035 get_state() 1035 int_type() 1035 length() 1035 lt() 1035 move() 1035 not_eof() 1035 off_type 1035 pos_type 1035 state_type 1035 to_char_type() 1035 read more..

  • Page - 1309

    1294 Index I user-defined type 450 vs. function requirement 706 classes, multiple implementation 624 classic C, locale 1114 classification, character 1033, 1142, 1154 class-oriented programming 11 cleanup, initialization and 354 clear() atomic_flag 1205 container 898, 901 error_code 875 string 1040 <climits> 865, 1162 <clocale> 864 clock 1015 from_time_t() 1015 is_steady() 1015 now 1015 to_time_t() 1015 read more..

  • Page - 1310

    – C – Index 1295 type checking 13 type safety 264 vs. run-time 790 compl, ˜ 258 complement operator ˜, bitwise 274 complete encapsulation 482 specialization 731 complex 61, 129, 535 _Complex 1278 complex example 542 <complex> 128–129, 865 complexity algorithm 931 amortized 895 asymptotic 895 function and code 306 guarantee 894 operation 894 composite operator 536 composition namespace 407, 409 read more..

  • Page - 1311

    1296 Index I const_cast 298, 302 constexpr and reference 312 const 262 function 43, 264, 307, 311 function arguments 266 immutability 42 type function 786 const_iterator 106, 896 const_local_iterator 896 const_pointer 896 const_pointer_cast(), shared_ptr 992 constraint 708 concept 708 constraints check 709 check concept 715 const_reference const_value_type& 896 const_reverse_iterator 896 construct() allocator 997 read more..

  • Page - 1312

    – C – Index 1297 emplace_back() 900 empty() 898 erase() 901 front() 900 hash 887 implementation of 888 inser t() 901 iterator algorithm 953 maxsize() 898 member types 896 object in 97 operation 893 operation overview 893 ordered 909 ordered associative 909 overview 101, 885 pop_back() 900 push_back() 900 representation of 888 reser ve() 898 resize() 898 return 104 sequence 886 shrinktofit() 898 size() 898 read more..

  • Page - 1313

    1298 Index I of exception 368 of vir tual base 510 on write 512 pointer and 510 requirement 890 semantics 510 shallow 511 shared_ptr and 511 strcpy() string 277 swap() and 514 union 215 _copy suffix 938 copy() 936 char_traits 1035 string 1041 copyable type, trivially 211 Copyable 716 copy_backward() 936 copy_if() 936 copy_n() 936 core language, ISO 38 cos() 1163 valarray 1170 cosh() 1163 valarray 1170 read more..

  • Page - 1314

    – D – Index 1299 data abstraction 11 member, template 675 race 115, 1197 race, avoiding 1197 race, initialization and 443 race, static variable 314 struct 454 data() array 976 string 1041 Date example 470 __DATE__ 340 DBL_MINEXP 1162 d.count(), duration 1010 D&E 10, 22 deadlock 118 mutex and 1223 deallocate array 281 deallocate() allocator 997 allocator_traits 998 deallocation 63 allocation and 277, read more..

  • Page - 1315

    1300 Index I = 524 a function 524 an operation 77 and operator delete() 556 conversion 524 destructor and 488 double 279 free-store allocation 525 naked 64 nothrow 285 nullptr 279 operator 63, 277 placement 283 premature 279 stack allocation 525 vs. missing, = 525 delete(), operator 282 delete[] 281 nullptr 282 delete()[], operator 282 deleter 987 denorm_min() 1161 dependency hardware 136 on template read more..

  • Page - 1316

    – D – Index 1301 from C enum 1275 from C function call 1274 from C function definition 1274 from C initialization and goto 1276 from C int implicit 1277 from C jump past initialization 1276 from C macro 1275 from C sizeof 1273 from C struct name 1276 from C struct scope 1273, 1276 from C void ∗ assignment 1275 silent 1273 difference_type 896 allocator_traits 998 iterator_traits read more..

  • Page - 1317

    1302 Index I E E infix 147 e, floating-point 146 %e format 1256 e infix 147 earliest C++ 12 ec.categor y() error_code 875 ECMAScript rules, format_default 1062 ECMAScript, regex 1057 EDOM 1163 efficiency and generality 862 efficient abstraction, elegant and 9 egrep, regex 1057 elegant and efficient abstraction 9 element access, Tuple 806 from sequence, delete 938 requirements 97, 890 read more..

  • Page - 1318

    – E – Index 1303 type 210, 673 equivalent() error_category 877 ERANGE 1163 erase() 99 container 901 string 1044 erase_after(), forward_list 908 erasure, type 733 errc POSIX 880 systemcategor y() 880 errno 350, 1163 <errno.h> 864 error detection, template 674 domain 1163 exception and 345, 348 function size and 306 handling 54, 251 handling, C-style 1163 handling, hierarchical 350 handling, multilevel read more..

  • Page - 1319

    1304 Index I Season 1120 Season << 1121, 1152 Season >> 1121, 1152 SI units 818 Slice_iter 1173 sor t() 333, 684 split() 394 Storable 632 String 668 String I/O 568 String_numput 1131 Sync_queue 1232 Tic_tac_toe 522 Tiny 543 Token 243 Token_stream 247 Tr acer 483 Tuple 802 Tuple get() 806 Vec 97 Vector 730 Window 635 examples and emphasis 7 exception 55, 344, 347 ... 369 and << 1132 and read more..

  • Page - 1320

    – E – Index 1305 externally imposed layout 212 extreme_value_distr ibution 1187 F F suffix 147 %F format 1256 %f format 1256 \f, formfeed 143 f suffix 147 fabs() 1163 facet access to 1119 _byname 1124 category 1124–1125 categor y 1113 class 1118 codecvt 1146 collate 1126 ctype 1143 identifier id 1119 lifetime of 1119 locale and 1109, 1113 messages 1150 money_get 1138 moneypunct 1135 money_put 1137 read more..

  • Page - 1321

    1306 Index I fisher_f_distribution 1188 fixed-length array 174 flags, match 1062 flags(), regex 1057 flexible composition of code 741 flip() bitset 979 float 146 bits in 1161 sizeof 150 float_denorm_style 1161 <float.h> 865 floating-point . 146 conversion 269 conversion to 270 e 146 environment, <cfenv> 866 hash of 915 literal 146 promotion 267 to int 270 type 139, 146 float_round_style 1161 read more..

  • Page - 1322

    – F – Index 1307 full expression 261 __FUNC__ 340 function 39 access 216 adaptor 967 and code complexity 306 and exception, C 352 argument 315 argument, array 184 argument const 307 argument names 308 argument passing 315, 482 argument type check 315 argument type conversion 315 argument types, vir tual 586 argument unused 308 arguments, constexpr 266 body 39, 307 body, tr y block as 98, read more..

  • Page - 1323

    1308 Index I G %g format 1256 %G format 1256 game 1180 gamma_distribution 1187 garbage collection, entanglement and 512 collection, pointers and 512 collection, shared_ptr 991 collector 278 Gaussian elimination, Matrix 850 Gavin 500 generality and iterator 929 efficiency and 862 generalized numeric algorithm 1176 slice 1175 general-purpose language, C++ 9 generate default operation 517 generate() 941 generated read more..

  • Page - 1324

    – H – Index 1309 has_denorm_loss 1161 Has_f example 799 has_facet() 1119 hash container 887 policy 919 table 100, 887 hash 887 of bitset 915, 980 of bool 915 of C-style string 915 of error_code 915 of floating-point 915 of integer 915 of pointer 915 of shared_ptr 915 of string 915 of thread::id 915 of typeindex 915 of u16string 915 of unique_ptr 915 of wstring 915 specialization 915 user-defined read more..

  • Page - 1325

    1310 Index I #ifndef 339, 441 $ii submatch 1061 imbue() iostream locale 1111 regex 1057 regex_traits 1070 immutability const 42 constexpr 42 immutable 461 locale is 1118 state 512 string literal 176 implementation alternative 620, 734 and interface 616 classes, multiple 624 definition 51 dependency type of integer literal 146 freestanding 137 hosted 137 inheritance 70, 578, 599, 637 interface and 419, read more..

  • Page - 1326

    –I– Index 1311 static member 506 syntax 159 uniform 492 union, default 216 universal 492 using constructors 491 without constructor 489 initialize 64 array 975 by constructor 492 initializer = 41 {} 41, 175, 202 () and 162 absence of 161 array 175 base 502 default 159 goto and 238 in-class 504, 506 in-class member 459 lack of 490 list 162 member 500–501 struct 202 initializer-list constructor read more..

  • Page - 1327

    1312 Index I specialization 733 internal linkage 421 international currency symbol 1136 internationalization, approaches to 1110 interoperability 16 INT_MAX 1162 introducer, lambda 293 int_type(), char_traits 1035 invalid_argument, bitset throws 868 invalidate iterator 898 invariant 56 and constructor 56 and default operation 520 class 484 class 454 enforcing 359 implicit 520 partially specified 522 rationale 485 read more..

  • Page - 1328

    –I– Index 1313 is_reference 1019 is_r value_reference 1018 is_same 1022 is_scalar 1019 is_signed 1020, 1161 is_sor ted() 942 isspace locale 1154 isspace() 1034 whitespace 250 is_specialized 1161 is_standard_layout 1020 is_steady(), clock 1015 istream >>, input 93 <istream> 864 istream_iterator 106 is_trivial 1020 is_trivially_assignable 1021 is_trivially_constructible 1021 is_trivially_copyable 1020 read more..

  • Page - 1329

    1314 Index I key and value 100 key_comp(), map 910 key_compare 896 key_eq(), unordered_map 919 key_equal 896 key_type 896 keyword 156 final, contextual 593 overr ide, contextual 590 kilo 1018 knuth_b 1184 L L" prefix 147 L’ prefix 147 L suffix 147 L’, wide-character literal 144 \L, regex 1054 \l, regex 1054 l suffix 147 label : 226 scope of 238 labs() 1164 lack of initializer 490 of read more..

  • Page - 1330

    – L – Index 1315 sub_match 1058 length_error, string throws 868 less 887 < 966 less_equal <= 966 less-than operator < 41 less-than-or-equal operator <= 41 letter, [[:alpha:]] 1054 lexical token 258 lexicographical order 949 lexicographical_compare() 949 libraries, C++ and 31 library 9 algorithm, standard 109 and error 344 C with Classes standard 25 C++11 standard 29 C++98 standard 26 container, read more..

  • Page - 1331

    1316 Index I load(), atomic<T> 1200 loader 420 load_factor(), unordered_map 919 local class, lambda and 291 currency symbol 1136 name, template argument 748 scope 157 static 314 variable 314 variable, initialization of 314 locale adding facet to 1117 and facet 1109, 1113 and iostream 1114, 1123 C 1114 C and C++ global 1154 class 1112 classic C 1114 concept 1109 constructor 1116 cultural preference read more..

  • Page - 1332

    – L – Index 1317 reference 190 M m, _m vs. 823 ->m, shared_ptr 992 _m vs. m 823 Machiavelli, Niccol`o 448 machines, language people and 9 macro 336 alternative to 338 difference from C 1275 predefined 340 template and 750 magnitude ratio, SI 1018 main() 39, 252, 441, 443 and initialization 442 argument to 253 argv argc 253 exception and 98 maintenance 437 make_error_code() 875 read more..

  • Page - 1333

    1318 Index I [] 833 ∗ 839 + 836–837 += 836 () 833, 846 = 832 {} initialization 843 access 846 and Vector 682 apply() 837 arithmetic 836 column() 833, 846 example 827 Gaussian elimination 850 implementation 840 linear equation 849 pivot 851 requirements 830 row() 833, 846 slice() 833, 841, 846 subscript 833 template 831 uses 828 zero-dimensional 848 Matrix_ref example 842 Max Munch 258 max() 950, 1161 read more..

  • Page - 1334

    – M – Index 1319 memberwise copy 453, 482, 519 default 519 initialization 489 move 519 memcpy() 210 mem_fn() 969 mem_fun() deprecated 967 mem_fun_ref() deprecated 967 memory access time 1195 buffer 1005 cache 1193 dynamic 277 location 1193 management, example of user-defined 561 model 1193 model, relaxed 1199 order 1195 representing 379 uninitialized 1005 <memor y> 112, 863, 1005 unique_ptr 987 read more..

  • Page - 1335

    1320 Index I by copy 516 by swap() 515 constructor 75, 482, 515 copy and 507 iterator 964 memberwise 519 of built-in type 516 swap() and 516 move() 76, 195, 516, 936, 1028 char_traits 1035 static_cast and 194 swap() and 516 move_backward() 936 moved-from state 507 move_if_noexcept() 1028 mt19937 1184 mt19937_64 1184 muddling through 347 multi-argument concept 714 multibyte character encoding 1146 read more..

  • Page - 1336

    – N – Index 1321 and specialization 736 interface implementation 404 name, lambda and 295 pollution 223 scope 157 struct 205 namespace 54, 391, 400 access 403 alias 406 alias reopen 398 and :: 392 and overloading 410 and scope 393 and versioning 412 chrono 1009 composition 407, 409 global 393 helper function and 475 inline 412 is open 398 linkage and 430 member declaration and definition 400 read more..

  • Page - 1337

    1322 Index I normal_distribution 129, 1188 no_state 883 nosubs, regex 1057 not ! 258 operator !, logical 274 not1() 967 not2() 967 notation enable_if 797 regular expression 1052 value of 527 not_eof(), char_traits 1035 not_eq, != 258 not-equal operator != 41 not_equal_to != 966 not-found 954 convention 928 nothrow guarantee 353 nothrow delete 285 new 285 nothrow_t 285 notify_all(), condition_var iable 1231 read more..

  • Page - 1338

    – O – Index 1323 operation acquire 1199 arithmetic 966 array 974 as argument, template 725 atomic 1196, 1198 bitset 979 choosing default 523 complexity 894 consume 1199 container 893 delete an 77 deque 893 forward_list 893, 907–908 fused 853 generate default 517 heap 948 invariant and default 520 iterator 959 list 893, 907 list 893, 901 map 893, 910 multi_map 893 multi_set 893 overview, read more..

  • Page - 1339

    1324 Index I noexcept 366 overloaded 62, 477 overloading, example of 561 precedence 255 predefined meaning for 531 return from 532 special 549 summary 255 symmetric 539 template literal 560 type conversion 543 user-defined 62, 529 user-defined binary 530 user-defined unary 530 operator "" 558 [], subscript 50 delete()[] 282 delete() 282 delete and size 557 delete(), delete and 556 delete(), read more..

  • Page - 1340

    – O – Index 1325 resolution, manual 330 return type and 328 scope and 328 overloaded function name 326 operator 62, 477 overloading and base 693 and derivation 693 bind() and 968 Enable_if and 801 example of operator 561 function template 689 namespace and 410 specialization and 737–738 override 66, 587, 598, 631 control 589 from vir tual base class 638 overr ide 590 contextual keyword 590 read more..

  • Page - 1341

    1326 Index I people and machines, language 9 perfection 17 performance final and 592 template 780 permutation 940 peta 1018 phone_book example 95 physical and logical const 462 program structure 419–420 pico 1018 piecewise_constant_distr ibution 1188 piecewiseconstr uct, pair 983 piecewise_linear_distr ibution 1188 p=is_sor ted_until() 942 pivot, Matrix 851 placeholders _1 967 _2 967 namespace 967 placement delete read more..

  • Page - 1342

    – P – Index 1327 and features 1267 pos_for mat(), moneypunct 1136 position, bit 978 position(), match_results 1060 positive_sign(), moneypunct 1136 POSIX <cerrno> 880 errc 880 thread support 1192 postcondition 330 pos_type char_traits 1035 streampos 1035 pow() 1163 valarray 1170 #pragma 341 precedence, operator 255 precondition 56, 330 failure 359 testing 359 predefined , 531 = 531 & 531 macro 340 read more..

  • Page - 1343

    1328 Index I prohibiting = 531 , 531 & 531 promise = 1237 constructor 1237 destructor 1237 future and 120, 1236 get_future() 1237 member set_exception() 120 member set_value() 120 packaged_task and future and 1238 set_exception() 1237 set_exception_at_thread_exit() 1237 set_value() set_value_at_thread_exit() 1237 swap() 1237 throws future_error 868 promise_already_satisfied 883 promotion bit-field 267 bool 267 character read more..

  • Page - 1344

    – R – Index 1329 RAII 64 rand(), random number 1189 Rand_int example 130 RAND_MAX 1189 random number 939, 1180 number 129 number rand() 1189 number, truly 1185 random distribution 129 engine 129 <random> 129, 865 random-access iterator 955 Random_access_iterator 716 random_access_iterator_tag 956 random_device 1185 random_shuffle() 939 range access 964 checking 174, 543 checking Vec 97 error 1163 for, read more..

  • Page - 1345

    1330 Index I ? 1052 = 1057 . 1052 alnum 1054 alpha 1054 assign 1057 awk 1057 \b 1055 \B 1055 basic 1057 blank 1054 cntrl 1054 collate 1057 \D 1054 d 1054 \d 1054 digit 1054 ECMAScript 1057 egrep 1057 extended 1057 flags() 1057 format() 1061 getloc() 1057 graph 1054 grep 1057 \i 1055 icase 1057 imbue() 1057 \l 1054 \L 1054 lower 1054 markcount() 1057 nosubs 1057 optimize 1057 print 1054 punct 1054 regular expression read more..

  • Page - 1346

    – R – Index 1331 list 907 remove_all_extents 1024 remove_const 1023 remove_copy() 938 remove_copy_if() 938 remove_cv 1023 removed, expor t 1270 remove_extent 1024 remove_if(), list 907 remove_reference 1023 remove_volatile 1023 rend() iterator 899 string 1044 reopen, namespace alias 398 reordering, instruction 1195 repeated base class 630 inheritance 630 repetition, regex 1053 replace() 938 string 1045 replace_copy() 938 read more..

  • Page - 1347

    1332 Index I from operator 532 function value 308 of void expression 310 type, void 40 returning results from task 116 return_temporar y_buffer() 1005 reuse of concrete type 478 reverse() 938 list 907 reverse_copy() 938 reverse_iterator 896, 960 rfind(), string 1046 Riemann zeta 1164 rotate() 939 rotate_copy() 939 round() 300 round_error() 1161 row(), Matrix 833, 846 rule, ODR, the one-definition 425 run-time read more..

  • Page - 1348

    – S – Index 1333 function 541 of class operations 471 set bitset and 977 operation 893 ordered 886 set() bitset 979 get() and 216 <set> 863 set_difference() 947 set_exception() promise 1237 promise member 120 set_exception_at_thread_exit(), promise 1237 set_intersection() 947 setjmp() 865, 1264 <setjmp.h> 865 set_symmetric_difference() 947 set_terminate() 372, 872 set_union() 947 set_value() promise promise read more..

  • Page - 1349

    1334 Index I operator new and 556 size() array 976 bitset 980 container 898 forward_list 907 match_results 1060 string 1040 valarray 1169 sizeof 40, 149 sizeof... 813 sizeof char 150 difference from C 1273 double 150 enum 223 enum class 222 float 150 int 150 long 150 long double 150 long long 150 result of 259 shor t 150 sizeof() 124 size_t 83, 150, 259, 865 size_type 896 sleep 1210 sleep_for(), read more..

  • Page - 1350

    – S – Index 1335 guarantee 135 header must include 866 include directory 424 ISO 135 layout type 211 library 6, 88, 111, 416 library, adding to 866 library algorithm 109 library basic guarantee 868 library, C with Classes 25 library, C++11 29 library, C++98 26 library container 101 library criteria 861 library design 860–861 library exception 868 library facilities 88, 860 library header 89, read more..

  • Page - 1351

    1336 Index I free 63, 167, 277 heap 277 store(), atomic<T> 1200 stoul(), string 1042 stoull(), string 1042 str() match_results 1060 sub_match 1058 strcpy() string copy 277 stream 864 stream 883 Streamable 716 <streambuf> 864 streamoff, off_type 1035 streampos, pos_type 1035 strict weak order 891 stride() 1172 string "", empty 177 and const, C-style 176 argument, template 724 character 864 read more..

  • Page - 1352

    – S – Index 1337 stoll() 1042 stoul() 1042 stoull() 1042 subscripting 1041 substr() 1048 swap() 1041 throws length_error 868 throws out_of_range 868 to_string() 1042 to_wstring() <string> 90, 864, 1035–1036 <string.h> 864 String_numput example 1131 strong guarantee 353 Strovstrup 1065 struct 47, 201 aggregate 202 and class 206, 454 array 207 class and 454 data 454 initializer 202 layout 203 member read more..

  • Page - 1353

    1338 Index I thread 1210 tuple 985 unique_lock 1227 unique_ptr 987 weak_ptr 994 swap_ranges() 942 switch 244 and enum 231 and if 230 compile-time 791 on enumeration 219 statement 43, 230 symbolic constant 264 symmetric operator 539 synchronization, volatile and 1207 Sync_queue example 1232 synonym – see typedef – see using syntax error 674 initialization 159 system, language library 15 system_categor y() read more..

  • Page - 1354

    – T – Index 1339 instantiation directive 744 instantiation, explicit 744 linkage 697 literal type argument 724 Matrix 831 member 670 member alias 676 member, class 675 member function 676 member template 678 member type 677 member typedef 676 member using 676 metaprogramming 779 name binding 745 nested template 678 operation as argument 725 overloading, function 689 parameter 722 parameter, non-type read more..

  • Page - 1355

    1340 Index I linear 894 logarithmic 894 memory access 1195 quadratic 894 traits 1016 __TIME__ 340 timed_mutex and recursive_timed_mutex 1224 constructor 1224 destructor 1224 lock() 1224 native_handle() 1224 native_handle_type 1224 tr ylock() 1224 tr ylock_for() 1224 tr ylock_until() 1224 unlock() 1224 <time.h> 863, 865 timeline, C++ 22 time_point 123 != 1014 += 1014 > 1014 >= 1014 = 1013 == 1014 -= 1014 - read more..

  • Page - 1356

    – T – Index 1341 element access 806 example 802 get() example 806 index 806 layout 804 list 802 use 804 tuple 127, 815, 984 != 985 > 985 >= 985 = 985 == 985 < 985 <= 985 << 817 allocator_arg_t 985 constructor 984 destructor 985 forward_as_tuple() 985 get() 985 maketuple() 985 swap() 985 tie() 985 tuple_cat 985 tuple_elements 985 tuple_size 985 uses_allocator 985 <tuple> 863 tuple_cat, read more..

  • Page - 1357

    1342 Index I tag 217 template member 677 trivial 211 trivially copyable 211 typename and name of 747 unsigned 144 user-defined 139, 201 user-defined operator and built-in 532 value 478 ::type convention 784 delayed checking 784 typedef alias 168 template and 694 template member 676 type-field 583 typeid() throws bad_typeid 868 type_index and type_info 1030 typeindex, hash of 915 <typeindex> 863 read more..

  • Page - 1358

    – U – Index 1343 mutex() 1227 owns_lock() 1227 release() 1227 swap() 1227 tr y_lock() 1227 tr y_lock_for() 1227 tr y_lock_until() 1227 unlock() 1227 unique_ptr 71, 112 < 987 <= 987 -> 987 ∗ 987 != 987 > 987 == 987 array 988 constructor 987 conversion to bool 987 destructor 987 get() 987 get_deleter() 987 hash of 915 <memor y> 987 nullptr 987 owner 987 release() 987 reset() 987 swap() 987 read more..

  • Page - 1359

    1344 Index I use_facet() 1119 user specialization 742 user-defined binary operator 530 facet 1123 facet Season_io 1120 hash 916 literal 822 literals 558 memory management, example of 561 operator 62, 529 operator = 575 operator + 532, 575 operator ++ 531, 554 operator += 531, 536, 575 operator -- 554 operator -> 552 operator and built-in type 532 operator and enum 532 operator, enum 220 read more..

  • Page - 1360

    – V – Index 1345 atan2() 1170 begin() 1170 cos() 1170 cosh() 1170 end() 1170 exp() 1170 iterator 1173 length 1169 log() 1170 log10() 1170 mathematical functions 1170 max() 1169 min() 1169 numerical 887 operations 1169–1170 pow() 1170 resize() 1169 sin() 1170 sinh() 1170 size() 1169 sqr t() 1170 subscripting 1168 subset of 1168 sum() 1169 tan() 1170 tanh() 1170 <valarray> 131, 865, 1166 valid pointer 140, read more..

  • Page - 1361

    1346 Index I destructor 70, 488, 598, 619 function 307, 585, 625 function argument types 586 function, definition of 586 function, implementation of 67 function, operator :: and 589 function, pure 598 function table vtbl 67, 587 pure 65 return type of 596 template function 679 void 148 ∗ 173 ∗ assignment, difference from C 1275 ∗, pointer to member 607 ∗, specialization and 730 read more..

  • Page - 1362

    This page intentionally left blank read more..

  • Page - 1363

    Preparation for Programming in the Real World From Bjarne Stroustrup, the inventor of C++, comes Programming: Principles and Practice Using C++, a general introduction to programming, including object-oriented programming and generic programming, and a solid introduction to the C++ programming language. Stroustrup presents modern C++ programming techniques from the start, introducing the C++ read more..

  • Page - 1364

    Register the Addison-Wesley, Exam Cram, Prentice Hall, Que, and Sams products you own to unlock great benefi ts. To begin the registration process, simply go to informit.com /register to sign in or create an account. You will then be prompted to enter the 10- or 13-digit ISBN that appears on the back cover of your product. informIT.com THE read more..

  • Page - 1365

    InformIT is a brand of Pearson and the online presence for the world’s leading technology publishers. It’s your source for reliable and qualified content and knowledge, providing access to the top brands, authors, and contributors from the tech community. informIT.com THE TRUSTED TECHNOLOGY LEARNING SOURCE LearnIT at InformIT Looking for a book, eBook, read more..

  • Page - 1366

    You love our titles and you love to share them with your colleagues and friends...why not earn some $$ doing it! If you have a website, blog, or even a Facebook page, you can start earning money by putting InformIT links on your page. Whenever a visitor clicks on these links and makes a purchase on informit.com, you earn commissions* on all sales! Every sale you read more..

Write Your Review