Discover millions of ebooks, audiobooks, and so much more with a free trial

Only $11.99/month after trial. Cancel anytime.

C++17 STL Cookbook
C++17 STL Cookbook
C++17 STL Cookbook
Ebook764 pages8 hours

C++17 STL Cookbook

Rating: 3 out of 5 stars

3/5

()

Read preview

About this ebook

About This Book
  • Learn the latest features of C++ and how to write better code by using the Standard Library (STL). Reduce the development time for your applications.
  • Understand the scope and power of STL features to deal with real-world problems.
  • Compose your own algorithms without forfeiting the simplicity and elegance of the STL way.
Who This Book Is For

This book is for intermediate-to-advanced C++ programmers who want to get the most out of the Standard Template Library of the newest version of C++: C++ 17.

LanguageEnglish
Release dateJun 28, 2017
ISBN9781787121768
C++17 STL Cookbook

Related to C++17 STL Cookbook

Related ebooks

Programming For You

View More

Related articles

Reviews for C++17 STL Cookbook

Rating: 3 out of 5 stars
3/5

1 rating0 reviews

What did you think?

Tap to rate

Review must be at least 10 words

    Book preview

    C++17 STL Cookbook - Jacek Galowicz

    C++17 STL Cookbook

    Over 90 recipes that leverage the powerful features of the standard library in C++17

    Jacek Galowicz

    BIRMINGHAM - MUMBAI

    C++17 STL Cookbook

    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 authors, 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: June 2017

    Production reference: 1230617

    Published by Packt Publishing Ltd.

    Livery Place

    35 Livery Street

    Birmingham

    B3 2PB, UK.

    ISBN 978-1-78712-049-5

    www.packtpub.com

    Credits

    About the Author

    Jacek Galowicz obtained his master of science in electrical engineering/computer engineering at RWTH Aachen University, Germany. While at university, he enjoyed working as a student assistant in teaching and research, and he participated in several scientific publications. During and after his studies, he worked as a freelancer and implemented applications as well as kernel drivers in C and C++, touching various areas, including 3D graphics programming, databases, network communication, and physics simulation. In recent years, he has been programming performance- and security-sensitive microkernel operating systems for Intel x86 virtualization at Intel and FireEye in Braunschweig, Germany. He has a strong passion for modern C++ implementations of low-level software, and he tries hard to combine high performance with an elegant coding style. Learning purely functional programming and Haskell in recent years triggered his drive to implement generic code with the aid of meta programming.

    Writing a book and founding a company at the same time was a great and interesting experience in my life and a lot of fun. The fun aspects, however, were only possible because of the support and patience of my wonderful girlfriend Viktoria, my fellow co-founders, and all my friends. Special thanks go to Arne Mertz for his invaluable and meticulous review suggestions, as well as Torsten Robitzki and Oliver Bruns from the C++ user group Hannover for their great feedback.

    About the Reviewer

    Arne Mertz is a C++ expert with over a decade of experience. He studied physics at the university of Hamburg, and he switched careers to become a software developer. His main background is in financial enterprise applications written in C++. Arne works at Zuhlke Engineering, Germany and is known for his blog, Simplify C++! (https://arne-mertz.de) on clean and maintainable C++.

    www.PacktPub.com

    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.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at service@packtpub.com 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.

    Why subscribe?

    Fully searchable across every book published by Packt

    Copy and paste, print, and bookmark content

    On demand and accessible via a web browser

    Customer Feedback

    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 on this book's Amazon page at https://www.amazon.com/dp/178712049X.

    If you'd like to join our team of regular reviewers, you can e-mail us at customerreviews@packtpub.com. We award our regular reviewers with free eBooks and videos in exchange for their valuable feedback. Help us be relentless in improving our products!

    Table of Contents

    Preface

    What this book covers

    What you need for this book

    Compiling and running the recipes

    Requirements for early adopters

    Who this book is for

    Sections

    Getting ready

    How to do it…

    How it works…

    There's more…

    See also

    Conventions

    Reader feedback

    Customer support

    Downloading the example code

    Errata

    Piracy

    Questions

    The New C++17 Features

    Introduction

    Using structured bindings to unpack bundled return values

    How to do it...

    How it works...

    There's more...

    Limiting variable scopes to if and switch statements

    How to do it...

    How it works...

    There's more...

    Profiting from the new bracket initializer rules

    How to do it...

    How it works...

    Letting the constructor automatically deduce the resulting template class type

    How to do it...

    How it works...

    There's more...

    Simplifying compile time decisions with constexpr-if

    How to do it...

    How it works...

    There's more...

    Enabling header-only libraries with inline variables

    How it's done...

    How it works...

    There's more...

    Implementing handy helper functions with fold expressions

    How to do it...

    How it works...

    There's more...

    Match ranges against individual items

    Check if multiple insertions into a set are successful

    Check if all the parameters are within a certain range

    Pushing multiple items into a vector

    STL Containers

    Introduction

    Contiguous storage

    List storage

    Search trees

    Hash tables

    Container adapters

    Using the erase-remove idiom on std::vector

    How to do it...

    How it works...

    There's more...

    Deleting items from an unsorted std::vector in O(1) time

    How to do it...

    How it works...

    Accessing std::vector instances the fast or the safe way

    How to do it...

    How it works...

    There's more...

    Keeping std::vector instances sorted

    How to do it...

    How it works...

    There's more...

    Inserting items efficiently and conditionally into std::map

    How to do it...

    How it works...

    There's more...

    Knowing the new insertion hint semantics of std::map::insert

    How to do it...

    How it works...

    There's more...

    Efficiently modifying the keys of std::map items

    How to do it...

    How it works...

    There's more...

    Using std::unordered_map with custom types

    How to do it...

    How it works...

    Filtering duplicates from user input and printing them in alphabetical order with std::set

    How to do it...

    How it works...

    std::istream_iterator

    std::inserter

    Putting it together

    Implementing a simple RPN calculator with std::stack

    How to do it...

    How it works...

    Stack handling

    Distinguishing operands from operations from user input

    Selecting and applying the right mathematical operation

    There's more...

    Implementing a word frequency counter with std::map

    How to do it...

    How it works...

    Implement a writing style helper tool for finding very long sentences in text with std::multimap

    How to do it...

    How it works...

     There's more...

    Implementing a personal to-do list using std::priority_queue

    How to do it...

    How it works...

    Iterators

    Introduction

    Iterator categories

    Input iterator

    Forward iterator

    Bidirectional iterator

    Random access iterator

    Contiguous iterator

    Output iterator

    Mutable iterator

    Building your own iterable range

    How to do it...

    How it works...

    Making your own iterators compatible with STL iterator categories

    How to do it...

    How it works...

    There's more...

    Using iterator adapters to fill generic data structures

    How to do it...

    How it works...

    std::back_insert_iterator

    std::front_insert_iterator

    std::insert_iterator

    std::istream_iterator

    std::ostream_iterator

    Implementing algorithms in terms of iterators

    How to do it...

    There's more...

    Iterating the other way around using reverse iterator adapters

    How to do it...

    How it works...

    Terminating iterations over ranges with iterator sentinels

    How to do it...

    Automatically checking iterator code with checked iterators

    How to do it...

    How it works...

    There's more...

    Building your own zip iterator adapter

    How to do it...

    There's more...

    Ranges library

    Lambda Expressions

    Introduction

    Defining functions on the run using lambda expressions

    How to do it...

    How it works...

    Capture list

    mutable (optional)

    constexpr (optional)

    exception attr (optional)

    return type (optional)

    Adding polymorphy by wrapping lambdas into std::function

    How to do it...

    How it works...

    Composing functions by concatenation

    How to do it...

    How it works...

    Creating complex predicates with logical conjunction

    How to do it...

    There's more...

    Calling multiple functions with the same input

    How to do it...

    How it works...

    Implementing transform_if using std::accumulate and lambdas

    How to do it...

    How it works...

    Generating cartesian product pairs of any input at compile time

    How to do it...

    How it works...

    STL Algorithm Basics

    Introduction

    Copying items from containers to other containers

    How to do it...

    How it works...

    Sorting containers

    How to do it...

    How it works...

    Removing specific items from containers

    How to do it...

    How it works...

    Transforming the contents of containers

    How to do it...

    How it works...

    Finding items in ordered and unordered vectors

    How to do it...

    How it works...

    Limiting the values of a vector to a specific numeric range with std::clamp

    How to do it...

    How it works...

    Locating patterns in strings with std::search and choosing the optimal implementation

    How to do it...

    How it works...

    Sampling large vectors

    How to do it...

    How it works...

    Generating permutations of input sequences

    How to do it...

    How it works...

    Implementing a dictionary merging tool

    How to do it...

    How it works...

    Advanced Use of STL Algorithms

    Introduction

    Implementing a trie class using STL algorithms

    How to do it...

    How it works...

    Implementing a search input suggestion generator with tries

    How to do it...

    How it works...

    There's more...

    Implementing the Fourier transform formula with STL numeric algorithms

    How to do it...

    How it works...

    Calculating the error sum of two vectors

    How to do it...

    How it works...

    Implementing an ASCII Mandelbrot renderer

    How to do it...

    How it works...

    Building our own algorithm - split

    How to do it...

    How it works...

    There's more...

    Composing useful algorithms from standard algorithms - gather

    How to do it...

    How it works...

    Removing consecutive whitespace between words

    How to do it...

    How it works...

    Compressing and decompressing strings

    How to do it...

    How it works...

    There's more...

    Strings, Stream Classes, and Regular Expressions

    Introduction

    Creating, concatenating, and transforming strings

    How to do it...

    How it works...

    Trimming whitespace from the beginning and end of strings

    How to do it...

    How it works...

    Getting the comfort of std::string without the cost of constructing std::string objects

    How to do it...

    How it works...

    Reading values from user input

    How to do it...

    How it works...

    Counting all words in a file

    How to do it...

    How it works...

    Formatting your output with I/O stream manipulators

    How to do it...

    How it works...

    Initializing complex objects from file input

    How to do it...

    How it works...

    Filling containers from std::istream iterators

    How to do it...

    How it works...

    Generic printing with std::ostream iterators

    How to do it...

    How it works...

    Redirecting output to files for specific code sections

    How to do it...

    How it works...

    Creating custom string classes by inheriting from std::char_traits

    How to do it...

    How it works...

    Tokenizing input with the regular expression library

    How to do it...

    How it works...

    Comfortably pretty printing numbers differently per context on the fly

    How to do it...

    Catching readable exceptions from std::iostream errors

    How to do it...

    How it works...

    Utility Classes

    Introduction

    Converting between different time units using std::ratio

    How to do it...

    How it works...

    There's more...

    Converting between absolute and relative times with std::chrono

    How to do it...

    How it works...

    Safely signalizing failure with std::optional

    How to do it...

    How it works...

    Applying functions on tuples

    How to do it...

    How it works...

    Quickly composing data structures with std::tuple

    How to do it...

    How it works...

    operator<< for tuples

    The zip function for tuples

    Replacing void* with std::any for more type safety

    How to do it...

    How it works...

    Storing different types with std::variant

    How to do it...

    How it works...

    Automatically handling resources with std::unique_ptr

    How to do it...

    How it works...

    Automatically handling shared heap memory with std::shared_ptr

    How to do it...

    How it works...

    There's more...

    Dealing with weak pointers to shared objects

    How to do it...

    How it works...

    Simplifying resource handling of legacy APIs with smart pointers

    How to do it...

    How it works...

    Sharing different member values of the same object

    How to do it...

    How it works...

    Generating random numbers and choosing the right random number engine

    How to do it...

    How it works...

    Generating random numbers and letting the STL shape specific distributions

    How to do it...

    How it works...

    Parallelism and Concurrency

    Introduction

    Automatically parallelizing code that uses standard algorithms

    How to do it...

    How it works...

    Which STL algorithms can we parallelize this way?

    How do those execution policies work?

    What does vectorization mean?

    Putting a program to sleep for specific amounts of time

    How to do it...

    How it works...

    Starting and stopping threads

    How to do it...

    How it works...

    Performing exception safe shared locking with std::unique_lock and std::shared_lock

    How to do it...

    How it works...

    Mutex classes

    Lock classes

    Avoiding deadlocks with std::scoped_lock

    How to do it...

    How it works...

    Synchronizing concurrent std::cout use

    How to do it...

    How it works...

    Safely postponing initialization with std::call_once

    How to do it...

    How it works...

    Pushing the execution of tasks into the background using std::async

    How to do it...

    How it works...

    There's more...

    Implementing the producer/consumer idiom with std::condition_variable

    How to do it...

    How it works...

    Implementing the multiple producers/consumers idiom with std::condition_variable

    How to do it...

    How it works...

    Parallelizing the ASCII Mandelbrot renderer using std::async

    How to do it...

    How it works...

    Implementing a tiny automatic parallelization library with std::future

    How to do it...

    How it works...

    Filesystem

    Introduction

    Implementing a path normalizer

    How to do it...

    How it works...

    There's more...

    Getting canonical file paths from relative paths

    How to do it...

    How it works...

    Listing all files in directories

    How to do it...

    How it works...

    Implementing a grep-like text search tool

    How to do it...

    How it works...

    There's more...

    Implementing an automatic file renamer

    How to do it...

    Implementing a disk usage counter

    How to do it...

    How it works...

    Calculating statistics about file types

    How to do it...

    Implementing a tool that reduces folder size by substituting duplicates with symlinks

    How to do it...

    How it works...

    There's more...

    Preface

    The C++17 STL Cookbook will teach you how to get the most out of C++17 by providing coding recipes that combine the C++ language and its standard library, the STL. Indeed, this book uses as much STL as possible, which is worth a bit of explanation.

    C++ is such a great and powerful language. It allows us to hide complex solutions behind simple high-level interfaces but, at the same time, to write low-level code where high performance and low overhead really matter. The ISO C++ Standard Committee works hard on improving the C++ standard. C++11 brought a lot of great features to C++, and so did C++14 and C++17.

    As of today, C++ is a language that provides language features and standard library facilities for sophisticated standard data structures and algorithms, automatic resource management pointers, lambda expressions, constant expressions, portable thread control for concurrent programming, regular expressions, random number generators, exceptions, variadic templates (the part of C++ for expressing template types is even Turing-complete!), user-defined literals, portable filesystem traversal, and so much more. This giant bunch of features makes it a general-purpose language ideal for implementing high-quality and high-performance software in all fields of the software industry.

    However, many C++ programmers eagerly learn C++ as a language but put its standard library, the STL, in the second place. Using the C++ language without the help that the standard library provides often leads to programs that look like C with classes, but not what modern programs in the 21st century should look like. This is very sad because using C++ like that means dropping half its strength.

    In the C++11 edition of his book, The C++ Programming Language, Bjarne Stroustrup writes, Please remember that those libraries and language features exist to support programming techniques for developing quality software. They are meant to be used in combination--as bricks in a building set--rather than to be used individually in relative isolation to solve a specific problem.

    This is exactly what this book and its recipes are about. All the recipes in this book are designed to be as near as possible to real-life problems, while at the same time, they do not rely on any external libraries other than the STL. This way, it is very simple to play around with each of them, without having to do confusing setup work. I really hope that you find inspiration in the recipes and, maybe, find some of them to be nice standard building blocks for solving higher-level problems with this great programming language.

    What this book covers

    Chapter 1, The New C++17 Features, specializes on the new and game-changing additions that the C++17 standard brought to C++ as a language, so we can concentrate on the additions to the STL in the following chapters.

    Chapter 2, STL Containers, explains how the STL's rich variety of container data structures got some upgrades with C++17. After having a look at the entire collection of the different containers, we will have a closer look on the new additions they got.

    Chapter 3, Iterators, explains iterators, which are an extremely important abstraction as they are the glue between the STL's algorithms and the container data structures, whenever they are combined. We are going to roll up the whole iterator concept from the ground to learn how to put them to the best use in all our programs.

    Chapter 4, Lambda Expressions, explores lambda expressions, which allow for some very interesting programming patterns. Inspired by purely functional programming languages, lambda expressions, which were first introduced in C++11, got some new features with C++14 and C++17.

    Chapter 5, STL Algorithm Basics, introduces the basics of the STL’s standard algorithms that are easy to use, very performant, well-tested, and highly generic. We will learn how to use them, so we can be productive by concentrating on solutions, instead of wasting time reinventing the wheel.

    Chapter 6, Advanced Use of STL Algorithms, demonstrates how to combine the STL’s basic algorithms in order to compose more complex ones in clean ways without code duplication. In this chapter, we will be creative and stick tightly to the STL while implementing solutions to more complex problems, and we will learn how to combine existing algorithms to create new ones that really fit our needs.

    Chapter 7, Strings, Stream Classes, and Regular Expressions, provides a detailed overview over the STL's powerful classes around strings, generic I/O streaming, and regular expressions. We will have an in-depth look into these parts of the STL in this chapter.

    Chapter 8, Utility Classes, explains the STL ways of generating random numbers, taking and measuring the time, managing dynamic memory, elegantly signalizing error conditions, and more. We will have a look at the extremely useful and portable utility classes that the C++ STL provides for such tasks and introduce the brand new ones that came with C++17.

    Chapter 9, Parallelism and Concurrency, showcases the existing C++ extensions for parallelism and concurrency which became very important topics at the time we entered the era of multi-core processors. First C++11, and then C++17, came with great additions that are of an enormous help whenever we need to implement programs that run on multiple cores and do things concurrently. So, we make sure we grasp these concepts in this chapter.

    Chapter 10, Filesystem, shows that although the STL always provided support for reading and manipulating individual files, C++17 got a lot of new value with its whole new operating system-independent library for the handling of filesystem paths and the traversal of directories. In this chapter, we will learn how to use it.

    What you need for this book

    All recipes in this book are kept as simple and self-contained as possible. They are easy to compile and run, but depending on the reader’s choice of operating system and compiler, there are differences. Let’s have a look how to compile and run all the recipes, and what else to pay attention to.

    Compiling and running the recipes

    All the code in this book has been developed and tested on Linux and MacOS, using the GNU C++ compiler, g++, and the LLVM C++ compiler, clang++.

    Building an example in the shell can be done with the following command using g++:

    Using clang++, the command is similar:

    Both the command-line examples assume that the file recipe_code.cpp is the text file containing your C++ code. After compiling the program, the executable binary will have the filename recipe_app and can be executed as follows:

    In a lot of examples, we read the content of entire files via standard input. In such cases, we use the standard UNIX pipes and the UNIX cat command to direct the file content into our app, as follows:

    This works on Linux and MacOS. In the Microsoft Windows shell, it works as follows:

    If you do not happen to run your programs from the command-line shell, but from the Microsoft Visual Studio IDE, then you need to open the dialogue, Configuration properties > Debugging, and add the < file.txt part to the command line of the app that Visual Studio uses for launching.

    Requirements for early adopters

    If you happen to read this book in the earliest days of C++17 and use bleeding- edge compilers to compile the code, you might experience that some recipes do not compile yet. This depends on how much of the C++17 STL has been implemented already in your STL distribution.

    While writing this book, it was necessary to add the path prefix experimental/ to the headers and . There might also be additional includes such as algorithm, numeric, and so on, in the experimental/ folder of your STL distribution, depending on how new and stable it is.

    The same applies for the namespace of brand new features. The parts of the library that were included from the experimental part of the STL are usually exported not within the std namespace but the std::experimental namespace.

    Who this book is for

    This book is not for you if you have no prior knowledge of writing and compiling C++ programs. If you read about the basics of this language already, this book is the ideal second book about C++ to take your knowledge to an advanced level.

    Apart from that, you are a good candidate for reading this book if you can identify yourself with one of the following bullet point descriptions:

    You have learned the basics of C++, but now, you don't have a clue where to go next, since the gap between your knowledge and the knowledge of an experienced C++ veteran is still large.

    You know C++ well, but your knowledge of the STL is limited.

    You know C++ from one of the older standards, such as C++98, C++11, or C++14. Depending on how far in the past you used C++ the last time, this book has a lot of nice new STL features and perks in store, ready for you to discover.

    Sections

    In this book, you will find several headings that appear frequently (Getting ready, How to do it, How it works, There's more, and See also).

    To give clear instructions on how to complete a recipe, we use these sections as follows:

    Getting ready

    This section tells you what to expect in the recipe, and describes how to set up any software or any preliminary settings required for the recipe.

    How to do it…

    This section contains the steps required to follow the recipe.

    How it works…

    This section usually consists of a detailed explanation of what happened in the previous section.

    There's more…

    This section consists of additional information about the recipe in order to make the reader more knowledgeable about the recipe.

    See also

    This section provides helpful links to other useful information for the recipe.

    Conventions

    In this book, you will find a number of text styles that distinguish between different kinds of information. Here are some examples of these styles and an explanation of their meaning.

    Code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles are shown as follows: The next step is to edit build.properties file.

    A block of code is set as follows:

    New terms and important words are shown in bold. Words that you see on the screen, for example, in menus or dialog boxes, appear in the text like this: Once done, click on Activate.

    Warnings or important notes appear in a box like this.

    Tips and tricks appear like this.

    Reader feedback

    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 feedback@packtpub.com, 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.

    Customer support

    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.

    Downloading the example code

    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/Cpp17-STL-Cookbook. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!

    Errata

    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

    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 copyright@packtpub.com with a link to the suspected pirated material.

    We appreciate your help in protecting our authors and our ability to bring you valuable content.

    Questions

    If you have a problem with any aspect of this book, you can contact us at questions@packtpub.com, and we will do our best to address the problem.

    The New C++17 Features

    In this chapter, we will cover the following recipes:

    Using structured bindings to unpack bundled return values

    Limiting variable scopes to if and switch statements

    Profiting from the new bracket initializer rules

    Letting the constructor automatically deduce the resulting template class type

    Simplifying compile-time decisions with constexpr-if

    Enabling header-only libraries with inline variables

    Implementing handy helper functions with fold expressions

    Introduction

    C++ got a lot of additions in C++11, C++14, and, most recently, C++17. By now, it is a completely different language compared to what it was just a decade ago. The C++ standard does not only standardize the language, as it needs to be understood by the compilers, but also the C++ standard template library (STL).

    This book explains how to put the STL to the best use with a broad range of examples. But at first, this chapter will concentrate on the most important new language features. Mastering them will greatly help you write readable, maintainable, and expressive code a lot.

    We will see how to access individual members of pairs, tuples, and structures comfortably with structured bindings and how to limit variable scopes with the new if and switch variable initialization capabilities. The syntactical ambiguities, which were introduced by C++11 with the new bracket initialization syntax, which looks the same for initializer lists, were fixed by new bracket initializer rules. The exact type of template class instances can now be deduced from the actual constructor arguments, and if different specializations of a template class will result in completely different code, this is now easily expressible with constexpr-if. The handling of variadic parameter packs in template functions became much easier in many cases with the new fold expressions. At last, it became more comfortable to define static globally accessible objects in header-only libraries with the new ability to declare inline variables, which was only possible for functions before.

    Some of the examples in this chapter might be more interesting for implementers of libraries than for developers who implement applications. While we will have a look at such features for completeness reasons, it is not too critical to understand all the examples of this chapter immediately in order to understand the rest of this book.

    Using structured bindings to unpack bundled return values

    C++17 comes with a new feature, which combines syntactic sugar and automatic type deduction: structured bindings. These help to assign values from pairs, tuples, and structs into individual variables. In other programming languages, this is also called unpacking.

    How to do it...

    Applying a structured binding in order to assign multiple variables from one bundled structure is always one step. Let's first see how it was done before C++17. Then, we can have a look at multiple examples that show how we can do it in C++17:

    Accessing individual values of an std::pair: Imagine we have a mathematical function, divide_remainder, which accepts a dividend and a divisor parameter and returns the fraction of both as well as the remainder. It returns those values using an std::pair bundle:

    Consider the following way of accessing the individual values of the resulting pair:

    Instead of doing it as shown in the preceding code snippet, we can now assign the individual values to individual variables with expressive names, which is much better to read:

    Structured bindings also work with std::tuple: Let's take the following example function, which gets us online stock information:

    Assigning its result to individual variables looks just like in the example before:

    Structured bindings also work with custom structures: Let's assume a structure like the following:

    Now, we can access these members using structured bindings. We can even do that in a loop, assuming we have a whole vector of those:

    How it works...

    Structured bindings are always applied with the same pattern:

    The list of variables var1, var2, ... must exactly match the number of variables contained by the expression being assigned from.

    The must be one of the following:

    An std::pair.

    An std::tuple.

    A struct. All members must be non-static and defined in the same base class. The first declared member is assigned to the first variable, the second member to the second variable, and so on.

    An array of fixed size.

    The type can be auto, const auto, const auto&, and even auto&&.

    Not only for the sake of performance, always make sure to minimize needless copies by using references when appropriate.

    If we write too many or not enough variables between the square brackets, the compiler will error out, telling us about our mistake:

    This example obviously tries to stuff a tuple variable with three members into only two variables. The compiler immediately chokes on this and tells us about our mistake:

    There's more...

    A lot of fundamental data structures from the STL are immediately accessible using structured bindings without us having to change anything. Consider, for example, a loop that prints all the items of an std::map:

    This particular example works because when we iterate over an std::map container, we get the std::pair nodes on every iteration step. Exactly these nodes are unpacked using the structured bindings feature (key_type is the species string and value_type is the population count size_t) in order to access them individually in the loop body.

    Before C++17, it was possible to achieve a similar effect using std::tie:

    This example shows how to unpack the resulting pair into two variables. The std::tie is less powerful than structured bindings in the sense that we have to define all the variables we want to bind to before. On the other hand, this example shows a strength of std::tie that structured bindings do not have: the value std::ignore acts as a dummy variable. The fraction part of the result is assigned to it, which leads to that value being dropped because we do not need it in that example.

    When using structured bindings, we don't have tie dummy variables, so we have to bind all the values to named variables. Doing so and ignoring some of them is efficient, nevertheless, because the compiler can optimize the unused bindings out easily.

    Back in the past, the divide_remainder function could have been implemented in the following way, using output parameters:

    Accessing it would have looked like the following:

    A lot of people will still prefer this over returning complex structures like pairs, tuples, and structs, arguing that this way the code would be faster, due to avoided intermediate copies of those values. This is not true any longer for modern compilers, which optimize intermediate copies away.

    Apart from the missing language features in C, returning complex structures via return value was considered slow for a long time because the object had to

    Enjoying the preview?
    Page 1 of 1