Modern C++ Design Generic Programming and Design Patterns Applied Andrei Alexandrescu f AAddison-Wesley Boston San Francisco New York Toronto Montreal London Munich Paris Madrid Capetown Sydney Tokyo Singapore Mexico City
Contents 1 Foreword by Scott Meyers Foreword by John Vlissides Preface Acknowledgments xi XV xvii xxi Parti Chapter 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 1.13 Techniques Policy-Based Class Design The Multiplicity of Software Design The Failure of the Do-It-All Interface Multiple Inheritance to the Rescue? The Benefit of Templates Policies and Policy Classes Enriched Policies Destructors of Policy Classes Optional Functionality Through Incomplete Instantiation Combining Policy Classes Customizing Structure with Policy Classes Compatible and Incompatible Policies Decomposing a Class into Policies 3 4 5 6 7 12 12 13 14 16 17 19 20
vi Contents Chapter 2 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10 2.11 Chapter 3 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 i Д12 3.13 3.14 3.15 Chapter 4 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 Techniques Compile-Time Assertions Partial Template Specialization Local Classes Mapping Integral Constants to Types Type-to-Type Mapping Type Selection Detecting Convertibility and Inheritance at Compile Time A Wrapper Around type_i nf о NullType and EmptyType Type Traits Typelists The Need for Typelists Defining Typelists Linearizing Typelist Creation Calculating Length Intermezzo Indexed Access Searching Typelists Appending to Typelists Erasing a Type from a Typelist Erasing Duplicates Replacing an Element in a Typelist Partially Ordering Typelists Class Generation with Typelists Typel i st Quick Facts Small-Object Allocation The Default Free Store Allocator The Workings of a Memory Allocator A Small-Object Allocator Chunks The Fixed-Size Allocator The SmallObjAllocator Class A Hat Trick Simple, Complicated, Yet Simple in the End Administrivia Small-Object Allocator Quick Facts 23 23 26 28 29 31 33 34 37 39 40 46 49 49 51 52 53 54 55 56 57 58 59 60 61 64 74 75 77 78 78 80 81 84 87 89 92 93 94 94
Contents vii Part II Chapter 5 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 5.11 5.12 5.13 5.14 5.15 5.16 Chapter 6 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10 6.11 6.12 6.13 Chapter 7 7.1 7.2 7.3 7.4 Components Generalized Functors The Command Design Pattern Command in the Real World C++ Callable Entities The Functor Class Template Skeleton Implementing the Forwarding Functor: :operator() Handling Functors Build One, Get One Free Argument and Return Type Conversions Handling Pointers to Member Functions Binding Chaining Requests Real-World Issues I: The Cost of Forwarding Functions Real-World Issues II: Heap Allocation Implementing Undo and Redo with Functor Functor Quick Facts Implementing Singletons Static Data + Static Functions!= Singleton The Basic C++ Idioms Supporting Singleton Enforcing the Singleton's Uniqueness Destroying the Singleton The Dead Reference Problem Addressing the Dead Reference Problem (I): The Phoenix Singleton Addressing the Dead Reference Problem (II): Singletons with Longevity Implementing Singletons with Longevity Living in a Multithreaded World Putting It All Together Working with Sing! etonhol der Si ngl etonhol der Class Template Quick Facts Smart Pointers Smart Pointers 101 The Deal Storage of Smart Pointers Smart Pointer Member Functions 97 99 100 102 103 104 108 110 112 114 115 119 122 122 124 125 126 126 129 130 131 132 133 135 137 139 142 145 148 153 155 155 157 157 158 160 161
viii Contents 7.5 Ownership-Handling Strategies 163 7.6 The Address-of Operator 170 7.7 Implicit Conversion to Raw Pointer Types 171 7.8 Equality and Inequality 173 7.9 Ordering Comparisons 178 7.10 Checking and Error Reporting 181 7.11 Smart Pointers to const and const Smart Pointers 182 7.12 Arrays 183 7.13 Smart Pointers and Multithreading 184 7.14 Putting It All Together 187 7.15 194 7.16 SmartPtr Quick Facts 194 Chapter 8 Object Factories 197 8.1 The Need for Object Factories 198 8.2 Object Factories in C++: Classes and Objects 200 8.3 Implementing an Object Factory 201 8.4 Type Identifiers 206 8.5 Generalization 207 8.6 Minutiae 210 8.7 Clone Factories 211 8.8 Using Object Factories with Other Generic Components 215 8.9 216 8.10 Factory Class Template Quick Facts 216 8.11 CIoneFactory Class Template Quick Facts 217 Chapter 9 Abstract Factory 219 9.1 The Architectural Role of Abstract Factory 219 9.2 A Generic Abstract Factory Interface 223 9.3 Implementing AbstractFactory 226 9.4 A Prototype-Based Abstract Factory Implementation 228 9.5 233 9.6 AbstractFactory and ConcreteFactory Quick Facts 233 Chapter 10 Visitor 235 10.1 Visitor Basics 235 10.2 Overloading and the Catch-All Function 242 10.3. An Implementation Refinement: The Acyclic Visitor 243 10.4 A Generic Implementation of Visitor 248 10.5 Back to the "Cyclic" Visitor 255 10.6 Hooking Variations 258 10.7 260 10.8 Visitor Generic Component Quick Facts 261
Contents ix Chapter 11 Multimethods 11.1 What Are Multimethods? 11.2 When Are Multimethods Needed? 11.3 Double Switch-on-Type: Brute Force 11.4 The Brute-Force Approach Automated 11.5 Symmetry with the Brute-Force Dispatcher 11.6 The Logarithmic Double Dispatcher 11.7 FnDi spatcher and Symmetry 11.8 Double Dispatch to Functors 11.9 Converting Arguments: stati c_cast or dynami c_cast? 11.10 Constant-Time Multimethods: Raw Speed 11.11 BasicDispatcher and BasicFastDispatcher as Policies 11.12 Looking Forward 11.13 11.14 Double Dispatcher Quick Facts 263 264 264 265 268 273 276 282 282 285 290 293 294 296 297 Appendix A.l A.2 A.3 A.4 A.5 A.6 A.7 A.8 Bibliography Index A Minimalist Multithreading Library A Critique of Multithreading Loki's Approach Atomic Operations on Integral Types Mutexes Locking Semantics in Object-Oriented Programming Optional vol ati 1 e Modifier Semaphores, Events, and Other Good Things 301 302 303 303 305 306 308 309 309 311 313