41,99 €
This book breaks down the C++ STL, teaching you how to extract its gems and apply them to your programming.
This book is for developers who would like to master the C++ STL and make full use of its components. Prior C++ knowledge is assumed.
Modern C++ has come a long way since 2011. The latest update, C++17, has just been ratified and several implementations are on the way.
This book is your guide to the C++ standard library, including the very latest C++17 features.
The book starts by exploring the C++ Standard Template Library in depth. You will learn the key differences between classical polymorphism and generic programming, the foundation of the STL. You will also learn how to use the various algorithms and containers in the STL to suit your programming needs. The next module delves into the tools of modern C++. Here you will learn about algebraic types such as std::optional, vocabulary types such as std::function, smart pointers, and synchronization primitives such as std::atomic and std::mutex. In the final module, you will learn about C++'s support for regular expressions and file I/O.
By the end of the book you will be proficient in using the C++17 standard library to implement real programs, and you'll have gained a solid understanding of the library's own internals.
This book takes a concise but comprehensive approach to explaining and applying the C++ STL, one feature at a time.
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 513
Veröffentlichungsjahr: 2017
BIRMINGHAM - MUMBAI
Copyright © 2017 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
First published: September 2017
Production reference: 1250917
ISBN 978-1-78712-682-4
www.packtpub.com
Author
Arthur O'Dwyer
Copy Editor
Safis Editing
Reviewer
Will Brennan
Project Coordinator
Prajakta Naik
Commissioning Editor
Merint Thomas Matthew
Proofreader
Safis Editing
Acquisition Editor
Sandeep Mishra
Indexer
Mariammal Chettiyar
Content Development Editor
Lawrence Veigas
Production Coordinator
Nilesh Mohite
Technical Editor
Dhiraj Chandanshive
Arthur O'Dwyer has used modern C++ in his day job for about ten years--since the days when "modern C++" meant "classic C++." Between 2006 and 2011 he worked on the Green Hills C++ compiler. Since 2014 he has organized a weekly C++ meetup in the San Francisco Bay Area, and he speaks regularly on topics such as those to be found in this book. Later this year, he will attend an ISO C++ committee meeting for the second time.
This is his first book.
Will Brennan is a C++/Python developer based in London with experience working on high performance image processing and machine learning applications. You can visit his GitHub link at https://github.com/WillBrennan.
For support files and downloads related to your book, please visit www.PacktPub.com.
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.comand as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.
https://www.packtpub.com/mapt
Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.
Fully searchable across every book published by Packt
Copy and paste, print, and bookmark content
On demand and accessible via a web browser
Thanks for purchasing this Packt book. At Packt, quality is at the heart of our editorial process. To help us improve, please leave us an honest review. If you'd like to join our team of regular reviewers, you can email us at [email protected]. We award our regular reviewers with free eBooks and videos in exchange for their valuable feedback. Help us be relentless in improving our products!
Preface
What this book covers
What you need for this book
Who this book is for
Conventions
Reader feedback
Customer support
Downloading the example code
Errata
Piracy
Questions
Classical Polymorphism and Generic Programming
Concrete monomorphic functions
Classically polymorphic functions
Generic programming with templates
Summary
Iterators and Ranges
The problem with integer indices
On beyond pointers
Const iterators
A pair of iterators defines a range
Iterator categories
Input and output iterators
Putting it all together
The deprecated std::iterator
Summary
The Iterator-Pair Algorithms
A note about headers
Read-only range algorithms
Shunting data with std::copy
Variations on a theme - std::move and std::move_iterator
Complicated copying with std::transform
Write-only range algorithms
Algorithms that affect object lifetime
Our first permutative algorithm: std::sort
Swapping, reversing, and partitioning
Rotation and permutation
Heaps and heapsort
Merges and mergesort
Searching and inserting in a sorted array with std::lower_bound
Deleting from a sorted array with std::remove_if
Summary
The Container Zoo
The notion of ownership
The simplest container: std::array<T, N>
The workhorse: std::vector<T>
Resizing a std::vector
Inserting and erasing in a std::vector
Pitfalls with vector<bool>
Pitfalls with non-noexcept move constructors
The speedy hybrid: std::deque<T>
A particular set of skills: std::list<T>
What are the special skills of std::list?
Roughing it with std::forward_list<T>
Abstracting with std::stack<T> and std::queue<T>
The useful adaptor: std::priority_queue<T>
The trees: std::set<T> and std::map<K, V>
A note about transparent comparators
Oddballs: std::multiset<T> and std::multimap<K, V>
Moving elements without moving them
The hashes: std::unordered_set<T> and std::unordered_map<K, V>
Load factor and bucket lists
Where does the memory come from?
Summary
Vocabulary Types
The story of std::string
Tagging reference types with reference_wrapper
C++11 and algebraic types
Working with std::tuple
Manipulating tuple values
A note about named classes
Expressing alternatives with std::variant
Visiting variants
What about make_variant? and a note on value semantics
Delaying initialization with std::optional
Revisiting variant
Infinite alternatives with std::any
std::any versus polymorphic class types
Type erasure in a nutshell
std::any and copyability
Again with the type erasure: std::function
std::function, copyability, and allocation
Summary
Smart Pointers
The origins of smart pointers
Smart pointers never forget
Automatically managing memory with std::unique_ptr<T>
Why C++ doesn't have the finally keyword
Customizing the deletion callback
Managing arrays with std::unique_ptr<T[]>
Reference counting with std::shared_ptr<T>
Don't double-manage!
Holding nullable handles with weak_ptr
Talking about oneself with std::enable_shared_from_this
The Curiously Recurring Template Pattern
A final warning
Denoting un-special-ness with observer_ptr<T>
Summary
Concurrency
The problem with volatile
Using std::atomic<T> for thread-safe accesses
Doing complicated operations atomically
Big atomics
Taking turns with std::mutex
"Taking locks" the right way
Always associate a mutex with its controlled data
Special-purpose mutex types
Upgrading a read-write lock
Downgrading a read-write lock
Waiting for a condition
Promises about futures
Packaging up tasks for later
The future of futures
Speaking of threads...
Identifying individual threads and the current thread
Thread exhaustion and std::async
Building your own thread pool
Improving our thread pool's performance
Summary
Allocators
An allocator is a handle to a memory resource
Refresher - Interfaces versus concepts
Defining a heap with memory_resource
Using the standard memory resources
Allocating from a pool resource
The 500 hats of the standard allocator
Carrying metadata with fancy pointers
Sticking a container to a single memory resource
Using the standard allocator types
Setting the default memory resource
Making a container allocator-aware
Propagating downwards with scoped_allocator_adaptor
Propagating different allocators
Summary
Iostreams
The trouble with I/O in C++
Buffering versus formatting
Using the POSIX API
Using the standard C API
Buffering in the standard C API
Formatting with printf and snprintf
The classical iostreams hierarchy
Streaming and manipulators
Streaming and wrappers
Solving the sticky-manipulator problem
Formatting with ostringstream
A note on locales
Converting numbers to strings
Converting strings to numbers
Reading a line or word at a time
Summary
Regular Expressions
What are regular expressions?
A note on backslash-escaping
Reifying regular expressions into std::regex objects
Matching and searching
Pulling submatches out of a match
Converting submatches to data values
Iterating over multiple matches
Using regular expressions for string replacement
A primer on the ECMAScript regex grammar
Non-consuming constructs
Obscure ECMAScript features and pitfalls
Summary
Random Numbers
Random numbers versus pseudo-random numbers
The problem with rand()
Solving problems with <random>
Dealing with generators
Truly random bits with std::random_device
Pseudo-random bits with std::mt19937
Filtering generator outputs with adaptors
Dealing with distributions
Rolling dice with uniform_int_distribution
Generating populations with normal_distribution
Making weighted choices with discrete_distribution
Shuffling cards with std::shuffle
Summary
Filesystem
A note about namespaces
A very long note on error-reporting
Using <system_error>
Error codes and error conditions
Throwing errors with std::system_error
Filesystems and paths
Representing paths in C++
Operations on paths
Statting files with directory_entry
Walking directories with directory_iterator
Recursive directory walking
Modifying the filesystem
Reporting disk usage
Summary
The C++ language has a long history, dating back to the 1980s. Recently it has undergone a renaissance, with major new features being introduced in 2011 and 2014. At press time, the C++17 standard is just around the corner.
C++11 practically doubled the size of the standard library, adding such headers as <tuple>, <type_traits>, and <regex>. C++17 doubles the library again, with additions such as <optional>, <any>, and <filesystem>. A programmer who’s been spending time writing code instead of watching the standardization process might fairly feel that the standard library has gotten away from him--that there’s so many new things in the library that he'll never be able to master the whole thing, or even to sort the wheat from the chaff. After all, who wants to spend a month reading technical documentation on std::locale and std::ratio, just to find out that they aren't useful in your daily work?
In this book, I'll teach you the most important features of the C++17 standard library. In the interest of brevity, I omit some parts, such as the aforementioned <type_traits>; but we'll cover the entire modern STL (every standard container and every standard algorithm), plus such important topics as smart pointers, random numbers, regular expressions, and the new-in-C++17 <filesystem> library.
I'll teach by example. You'll learn to build your own iterator type; your own memory allocator using std::pmr::memory_resource; your own thread pool using std::future.
I'll teach concepts beyond what you'd find in a reference manual. You'll learn the difference between monomorphic, polymorphic, and generic algorithms (Chapter 1, Classical Polymorphism and Generic Programming); what it means for std::string or std::any to be termed a "vocabulary type" (Chapter 5, Vocabulary Types); and what we might expect from future C++ standards in 2020 and beyond.
I assume that you are already reasonably familiar with the core language of C++11; for example, that you already understand how to write class and function templates, the difference between lvalue and rvalue references, and so on.
Chapter 1, Classical Polymorphism and Generic Programming, covers classical polymorphism (virtual member functions) and generic programming (templates).
Chapter 2, Iterators and Ranges, explains the concept of iterator as a generalization of pointer, and the utility of half-open ranges expressed as a pair of iterators.
Chapter 3, The Iterator-Pair Algorithms, explores the vast variety of standard generic algorithms that operate on ranges expressed as iterator-pairs.
Chapter 4, The Container Zoo, explores the almost equally vast variety of standard container class templates, and which containers are suitable for which jobs.
Chapter 5, Vocabulary Types, walks you through algebraic types such as std::optional. and ABI-friendly type-erased types such as std::function.
Chapter 6, Smart Pointers, teaches the purpose and use of smart pointers.
Chapter 7, Concurrency, covers atomics, mutexes, condition variables, threads, futures, and promises.
Chapter 8, Allocators, explains the new features of C++17's <memory_resource> header.
Chapter 9, Iostreams, explores the evolution of the C++ I/O model, from <unistd.h> to <stdio.h> to <iostream>.
Chapter 10, Regular Expressions, teaches regular expressions in C++.
Chapter 11, Random Numbers, walks you through C++'s support for pseudo-random number generation.
Chapter 12, Filesystem, covers the new-in-C++17 <filesystem> library.
As this book is not a reference manual, it might be useful for you to have a reference manual, such as cppreference (en.cppreference.com/w/cpp), at your side to clarify any confusing points. It will definitely help to have a C++17 compiler handy. At press time, there are several more or less feature-complete C++17 implementations, including GCC, Clang, and Microsoft Visual Studio. You can run them locally or via many free online compiler services, such as Wandbox (wandbox.org), Godbolt (gcc.godbolt.org), and Rextester (rextester.com).
This book is for developers who would like to master the C++17 STL and make full use of its components. Prior C++ knowledge is assumed.
Feedback from our readers is always welcome. Let us know what you think about this book--what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of. To send us general feedback, simply e-mail [email protected], and mention the book's title in the subject of your message. If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at www.packtpub.com/authors.
Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.
You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you. You can download the code files by following these steps:
Log in or register to our website using your e-mail address and password.
Hover the mouse pointer on the
SUPPORT
tab at the top.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box.
Select the book for which you're looking to download the code files.
Choose from the drop-down menu where you purchased this book from.
Click on
Code Download
.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR / 7-Zip for Windows
Zipeg / iZip / UnRarX for Mac
7-Zip / PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Mastering-the-Cpp17-STL. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books--maybe a mistake in the text or the code--we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title. To view the previously submitted errata, go to https://www.packtpub.com/books/content/support and enter the name of the book in the search field. The required information will appear under the Errata section.
Piracy of copyrighted material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy. Please contact us at [email protected] with a link to the suspected pirated material. We appreciate your help in protecting our authors and our ability to bring you valuable content.
If you have a problem with any aspect of this book, you can contact us at [email protected], and we will do our best to address the problem.
The C++ standard library has two distinct, yet equally important, missions. One of these missions is to provide rock-solid implementations of certain concrete data types or functions that have tended to be useful in many different programs, yet aren't built into the core language syntax. This is why the standard library contains std::string, std::regex, std::filesystem::exists, and so on. The other mission of the standard library is to provide rock-solid implementations of widely used abstract algorithms such as sorting, searching, reversing, collating, and so on. In this first chapter, we will nail down exactly what we mean when we say that a particular piece of code is "abstract," and describe the two approaches that the standard library uses to provide abstraction: classical polymorphism and generic programming.
We will look at the following topics in this chapter:
Concrete (monomorphic) functions, whose behavior is not parameterizable
Classical polymorphism by means of base classes, virtual member functions, and inheritance
Generic programming by means of concepts, requirements, and models
The practical advantages and disadvantages of each approach
Both classical polymorphism and generic programming deal with the essential problem of parameterizing the behavior of an algorithm: for example, writing a search function that works with any arbitrary matching operation.
Classical polymorphism tackles that problem by specifying an abstract base class with a closed set of virtual member functions, and writing polymorphic functions that accept pointers or references to instances of concrete classes inheriting from that base class.
Generic programming tackles the same problem by specifying a concept with a closed set of requirements, and instantiating function templates with concrete classes modeling that concept.
Classical polymorphism has trouble with higher-level parameterizations (for example, manipulating function objects of any signature) and with relationships between types (for example, manipulating the elements of an arbitrary container). Therefore, the Standard Template Library uses a great deal of template-based generic programming, and hardly any classical polymorphism.
When you use generic programming, it will help if you keep in mind the conceptual requirements of your types, or even write them down explicitly; but as of C++17, the compiler cannot directly help you check those requirements.
In the previous chapter, we implemented several generic algorithms that operatedon containers, but in an inefficient manner. In this chapter, you'll learn:
How and why C++ generalizes the idea of pointers to create the
iterator
concept
The importance of
ranges
in C++, and the standard way to express a half-open range as a pair of iterators
How to write your own rock-solid, const-correct iterator types
How to write generic algorithms that operate on iterator pairs
The standard iterator hierarchy and its algorithmic importance
In this chapter, we've learned that traversal is one of the most fundamental things you can do with a data structure. However, raw pointers alone are insufficient for traversing complicated structures: applying ++ to a raw pointer often doesn't "go on to the next item" in the intended way.
The C++ Standard Template Library provides the concept of iterator as a generalization of raw pointers. Two iterators define a range of data. That range might be only part of the contents of a container; or it might be unbacked by any memory at all, as we saw with getc_iterator and putc_iterator
