This document is intended for knowledgeable users of C (or any other language using a C-like grammar, like Perl or Java) who would like to know more about, or make the transition to, C++. This document is the main textbook for Frank's C++ programming courses, which are yearly organized at the University of Groningen. The C++ Annotations do not cover all aspects of C++, though. In particular, C++'s basic grammar is not covered when equal to C's grammar. Any basic book on C may be consulted to refresh that part of C++'s grammar.
Conditions of Use
This book is licensed under a Creative Commons License (CC BY). You can download the ebook C++ Annotations for free.
- Title
- C++ Annotations
- Author(s)
- Frank Brokken
- Published
- 2024-05-27
- Edition
- 1
- Format
- eBook (pdf, epub, mobi)
- Pages
- 1158
- Language
- English
- ISBN-10
- B00BL773QA
- License
- CC BY
- Book Homepage
- Free eBook, Errata, Code, Solutions, etc.
Overview Of The Chapters Introduction What's new in the C++ Annotations C++'s history History of the C++ Annotations Compiling a C program using a C++ compiler Compiling a C++ program C++: advantages and claims What is Object-Oriented Programming? Differences between C and C++ The function `main' End-of-line comment Strict type checking Function Overloading Default function arguments NULL-pointers vs. 0-pointers and nullptr The `void' parameter list The ` define __cplusplus' Using standard C functions Header files for both C and C++ Defining local variables The keyword `typedef' Functions as part of a struct Evaluation order of operands A First Impression Of C++ Notable differences with C Using the keyword `const' Namespaces The scope resolution operator :: `cout', `cin', and `cerr' Functions as part of structs Data hiding: public, private and class Structs in C vs. structs in C++ Several additions to C's grammar References Rvalue References Lvalues, rvalues and more Strongly typed enumerations Initializer lists Initializers for bit-fields Type inference using `auto' Defining types and `using' declarations Range-based for-loops Raw String Literals Binary constants Selection statements with initializers Attributes Three-way comparison () New language-defined data types The data type `bool' The data type `wchar_t' Unicode encoding The data type `long long int' The data type `size_t' The data type `std::byte' Digit separators A new syntax for casts The `static_cast'-operator The `const_cast'-operator The `reinterpret_cast'-operator The `dynamic_cast'-operator Casting 'shared_ptr' objects Keywords and reserved names in C++ Namespaces Namespaces Defining namespaces Referring to entities The standard namespace Nesting namespaces and namespace aliasing The std::chrono namespace (handling time) Time resolutions: std::ratio Amounts of time: std::chrono::duration Clocks measuring time Points in time: std::chrono::time_point The std::filesystem namespace the '__file_clock' type The class 'error_code' Names of file system entries: path Handling directories: directory_entry Types (file_type) and permissions (perms) of file system elements: file_status Information about the space of file systems: space_info File system exceptions: filesystem_error The `string' Data Type Operations on strings A std::string reference Initializers Iterators Operators Member functions Conversion functions std::string_view The IO-stream Library Special header files The foundation: the class `ios_base' Interfacing `streambuf' objects: the class `ios' Condition states Formatting output and input Output Basic output: the class `ostream' Output to files: the class `ofstream' Output to memory: the class `ostringstream' The `put_time' manipulator Input Basic input: the class `istream' Input from files: the class `ifstream' Input from memory: the class `istringstream' Copying streams Coupling streams Advanced topics Moving streams Redirecting streams Reading AND Writing streams Classes The constructor A first application Constructors: with and without arguments Ambiguity resolution Types `Data' vs. `Data()' Superfluous parentheses Existing types Objects inside objects: composition Composition and (const) objects: (const) member initializers Composition and reference objects: reference member initializers Data member initializers Delegating constructors Uniform initialization Defaulted and deleted class members Const member functions and const objects Anonymous objects The keyword `inline' Defining members inline When to use inline functions Inline variables Local classes: classes inside functions The keyword `mutable' Header file organization Using namespaces in header files Modules Sizeof applied to class data members Static Data And Functions Static data Private static data Public static data Initializing static const data Generalized constant expressions (constexpr) Static member functions Calling conventions Classes And Memory Allocation Operators `new' and `delete' Allocating arrays Deleting arrays Enlarging arrays Managing `raw' memory The `placement new' operator The destructor Object pointers revisited The function set_new_handler() The assignment operator Overloading the assignment operator The `this' pointer Sequential assignments and this The copy constructor: initialization vs. assignment Revising the assignment operator Swapping Moving data The move constructor (dynamic data) The move constructor (composition) Move-assignment Revising the assignment operator (part II) Moving and the destructor Move-only classes Default move constructors and assignment operators Moving: implications for class design Copy Elision and Return Value Optimization Unrestricted Unions Implementing the destructor Embedding an unrestricted union in a surrounding class Swapping unrestricted unions Assignment Aggregate Data Types Conclusion Exceptions Exception syntax An example using exceptions Anachronisms: `setjmp' and `longjmp' Exceptions: the preferred alternative Throwing exceptions The empty `throw' statement The try block Catching exceptions The default catcher Functions unable to throw exceptions: the `noexcept' keyword Iostreams and exceptions Standard exceptions Standard exceptions: to use or not to use? System error, error_category, and error_condition The class `std::error_category' The class `std::error_condition' The class system_error Exception propagation: std::exception_ptr Exception guarantees The basic guarantee The strong guarantee The nothrow guarantee Function try blocks Exceptions in constructors Exceptions in destructors More Operator Overloading Overloading `operator[]()' Multi-argument `operator[]()' Overloading insertion and extraction operators Conversion operators An alternative implementation of the `byte' type The keyword `explicit' Explicit conversion operators Overloading increment and decrement operators Overloading binary operators Member function reference bindings (& and &&) The three-way comparison operator `' Overloading `operator new(size_t)' Overloading `operator delete(void *)' Operators `new[]' and `delete[]' Overloading `new[]' Overloading `delete[]' The `operator delete(void *, size_t)' family `new[]', `delete[]' and exceptions Function Objects Constructing manipulators Lambda expressions Lambda expressions: syntax Using lambda expressions The case of [io]fstream::open() User-defined literals Overloadable operators Abstract Containers Notations used in this chapter The `pair' container Allocators Available Containers The `array' container The `vector' container The `list' container The `queue' container The `priority_queue' container The `deque' container The `map' container The `multimap' container The `set' container The `multiset' container The `stack' container The `unordered_map' container (`hash table') The `unordered_set' container Heterogeneous lookup The `complex' container Inheritance Related types Inheritance depth: desirable? Access rights: public, private, protected Public, protected and private derivation Promoting access rights The constructor of a derived class Move construction Move assignment Inheriting constructors Aggregate Initializations The destructor of a derived class Redefining member functions Multiple inheritance Conversions between base classes and derived classes Conversions with object assignments Conversions with pointer assignments Using non-default constructors with new[] Polymorphism Virtual functions Constructors of polymorhic classes Virtual destructors Pure virtual functions Implementing pure virtual functions Explicit virtual overrides Virtual functions and multiple inheritance Ambiguity in multiple inheritance Virtual base classes When virtual derivation is not appropriate Run-time type identification The dynamic_cast operator The `typeid' operator Inheritance: when to use to achieve what? The `streambuf' class Protected `streambuf' members The class `filebuf' Safely interfacing streams to another std::streambuf Reading and writing using `std::iostream' A polymorphic exception class How polymorphism is implemented Undefined reference to vtable ... Virtual constructors Friends Friend functions Extended friend declarations Classes Having Pointers To Members Pointers to members: an example Defining pointers to members Using pointers to members Pointers to static members Pointer sizes Nested Classes Defining nested class members Declaring nested classes Accessing private members in nested classes Nesting enumerations Empty enumerations Revisiting virtual constructors The Standard Template Library Predefined function objects Arithmetic function objects Relational function objects Logical function objects The `std::not_fn' negator Iterators std::distance and std::size Insert iterators Iterators for `istream' objects Iterators for `ostream' objects Moving elements to another container The class 'unique_ptr' Defining `unique_ptr' objects Creating a plain `unique_ptr' Moving another `unique_ptr' Pointing to a newly allocated object Operators and members Using `unique_ptr' objects for arrays The class `shared_ptr' Defining `shared_ptr' objects Creating a plain `shared_ptr' Pointing to a newly allocated object Operators and members Casting shared pointers Using `shared_ptr' objects for arrays Smart `smart pointer' construction: `make_shared' and `make_unique' Classes having pointer data members Comparison classes The class `weak_equality' The class `strong_equality' The class `partial_ordering' The class `weak_ordering' The class `strong_ordering' Regular Expressions The regular expression mini language Defining regular expressions: std::regex Retrieving matches: std::match_results Regular expression matching functions Randomization and Statistical Distributions Random Number Generators Statistical distributions tie Optional return values The STL Generic Algorithms The Generic Algorithms Execution policies accumulate adjacent_difference adjacent_find all_of / any_of / none_of begin / end binary_search copy / copy_if copy_backward count / count_if equal equal_range exchange fill / fill_n find / find_if / find_if_not find_end find_first_of for_each generate / generate_n includes inner_product inplace_merge iota is_partitioned is_permutation is_sorted is_sorted_until iter_swap lexicographical_compare lower_bound max / min max_element / min_element / minmax_element merge minmax mismatch move / move_backward next_permutation / prev_permutation nth_element partial_sort / partial_sort_copy partial_sum partition / partition_point / stable_partition partition_copy reduce remove / remove_if / remove_copy / remove_copy_if replace / replace_if / replace_copy / replace_copy_if reverse / reverse_copy rotate / rotate_copy sample search / search_n set_difference set_intersection set_symmetric_difference set_union sort / stable_sort swap / swap_ranges transform transform_reduce handling uninitialized memory unique unique_copy upper_bound Heap algorithms Multi Threading Multi Threading The namespace std::this_thread The class std::thread The class std::jthread Synchronization (mutexes) Initialization in multi-threaded programs Shared mutexes Locks and lock handling Deadlocks Shared locks Scoped locks Event handling (condition variables) The class std::condition_variable The class std::condition_variable_any An example using condition variables Atomic actions: mutexes not required An example: threaded quicksort Shared States Asynchronous return objects: std::future The std::future_error exception and the std::future_errc enum Shared asynchronous return objects: std::shared_future Starting a new thread: std::async Preparing a task for execution: std::packaged_task The class `std::promise' An example: multi-threaded compilations Transactional Memory Synchronizing output to streams The `std::syncbuf' streambuf Multi-threaded compilations using `osyncstream' Function and Variable Templates Defining function templates Considerations regarding template parameters Auto and decltype Late-specified return type Passing arguments by reference (reference wrappers) Using local and unnamed types as template arguments Template parameter deduction Lvalue transformations Qualification transformations Transformation to a base class The template parameter deduction algorithm Template type contractions Declaring function templates Instantiation declarations Instantiating function templates Instantiations: no `code bloat' Using explicit template types Overloading function templates An example using overloaded function templates Ambiguities when overloading function templates Declaring overloaded function templates Specializing templates for deviating types Avoiding too many specializations Declaring specializations Complications when using the insertion operator Static assertions Numeric limits Polymorphous wrappers for function objects Compiling template definitions and instantiations The function selection mechanism Determining the template type parameters SFINAE: Substitution Failure Is Not An Error Conditional function definitions using `if constexpr' Summary of the template declaration syntax Variables as templates (template variables) Class Templates Template Argument Deduction Defining class templates Constructing the circular queue: CirQue Non-type parameters Member templates CirQue's constructors and member functions Using CirQue objects Default class template parameters Declaring class templates Preventing template instantiations Generic lambda expressions Static data members Extended use of the keyword `typename' Specializing class templates for deviating types Example of a class specialization Partial specializations Intermezzo: some simple matrix algebraic concepts The Matrix class template The MatrixRow partial specialization The MatrixColumn partial specialization The 1x1 matrix: avoid ambiguity Variadic templates Defining and using variadic templates Perfect forwarding The unpack operator Non-type variadic templates Folding expressions Tuples Tuples and structured bindings Computing the return type of function objects Instantiating class templates Processing class templates and instantiations Declaring friends Non-templates used as friends in templates Templates instantiated for specific types as friends Unbound templates as friends Extended friend declarations Class template derivation Deriving ordinary classes from class templates Deriving class templates from class templates Deriving class templates from ordinary classes Static Polymorphism An example of static polymorphism Converting dynamic polymorphic classes to static polymorphic classes Using static polymorphism to avoid reimplementations Class templates and nesting Constructing iterators Implementing a `RandomAccessIterator' Implementing a `reverse_iterator' Advanced Template Use Subtleties Type resolution for base class members ::template, .template and ->template Template Meta Programming Values according to templates Selecting alternatives using templates Templates: Iterations by Recursion User-defined literals Template template parameters Policy classes - I Policy classes - II: template template parameters Structure by Policy Alias Templates Trait classes Distinguishing class from non-class types Available type traits Defining `ErrorCodeEnum' and 'ErrorConditionEnum' enumerations Deriving classes from std::error_category Using `noexcept' when offering the `strong guarantee' More conversions to class types Types to types An empty type Type convertibility Template TypeList processing The length of a TypeList Searching a TypeList Selecting from a TypeList Prefixing/Appending to a TypeList Erasing from a TypeList Using a TypeList The Wrap and Multi class templates The MultiBase class template Support templates Using Multi Expression Templates Designing an Expression Template Implementing an Expression Template The BasicType trait class and ordering classes Concepts Defining concepts Requirements Predefined concepts Applying concepts to template parameter packs Applying concepts to free functions Implementing constrained class members Constrained partial specializations Coroutines Defining a coroutine The coroutine's State class (promise_type) Simplifying the state class Embedding coroutines in classes The `Reader' coroutine handler The `Writer' coroutine handler `Awaitables', `Awaiters' and `co_await' The class `Awaiter' Accessing State from inside coroutines Finite State Automatons via coroutines The `Start' handler class Completing the Finite State Automaton Recursive coroutines Recursively calling recursiveCoro Beyond a single recursive call Coroutine iterators Visiting directories using coroutines The `Dir' class showing directory entries Visiting directories using coroutines Functions vs. coroutines Concrete Examples Using file descriptors with `streambuf' classes Classes for output operations Classes for input operations Fixed-sized field extraction from istream objects The `fork' system call A basic Fork class Parents and Children Redirection revisited The `Daemon' program The class `Pipe' The class `ParentSlurp' Communicating with multiple children Adding binary operators to classes Merely using operators The CRTP and defining operator function templates Insertion and extraction Distinguishing lvalues from rvalues with operator[]() Implementing a `reverse_iterator' Using `bisonc++' and `flexc++' Using `flexc++' to create a scanner Using `bisonc++' and `flexc++' Index
Related Books