9

Library Overview

Why waste time learning when ignorance is instantaneous?

– Hobbes

9.1 Introduction

No significant program is written in just a bare programming language. First, a set of libraries is developed. These then form the basis for further work. Most programs are tedious to write in the bare language, whereas just about any task can be rendered simple by the use of good libraries.

Continuing from Chapters 18, Chapters 918 give a quick tour of key standard-library facilities. I very briefly present useful standard-library types, such as string, ostream, variant, vector, map, path, unique_ptr, thread, regex, system_clock, time_zone, and complex, as well as the most common ways of using them.

As in Chapters 18, you are strongly encouraged not to be distracted or discouraged by an incomplete understanding of details. The purpose of this chapter is to convey a basic understanding of the most useful library facilities.

The specification of the standard library is over two thirds of the ISO C++ standard. Explore it, and prefer it to home-made alternatives. Much thought has gone into its design, more still into its implementations, and much effort will go into its maintenance and extension.

The standard-library facilities described in this book are part of every complete C++ implementation. In addition to the standard-library components, most implementations offer “graphical user interface” systems (GUIs), Web interfaces, database interfaces, etc. Similarly, most application-development environments provide “foundation libraries” for corporate or industrial “standard” development and/or execution environments. Beyond that, there are many thousands of libraries supporting specialized application areas. Here, I do not describe libraries, systems, or environments beyond the standard-libraries. The intent is to provide a self-contained description of C++ as defined by its standard [C++,2020] and to keep the examples portable. Naturally, a programmer is encouraged to explore the more extensive facilities available on most systems.

9.2 Standard-Library Components

The facilities provided by the standard library can be classified like this:

  • Run-time language support (e.g., for allocation, exceptions, and run-time type information).

  • The C standard library (with very minor modifications to minimize type system violations).

  • Strings with support for international character sets, localization, and read-only views of substrings (§10.2).

  • Support for regular expression matching (§10.4).

  • I/O streams is an extensible framework for input and output to which users can add their own types, streams, buffering strategies, locales, and character sets (Chapter 11). It also offers facilities for flexible output formatting (§11.6.2).

  • A library for manipulating file systems in a portable manner (§11.9).

  • A framework of containers (such as vector and map; Chapter 12) and algorithms (such as find(), sort(), and merge(); Chapter 13). This framework, conventionally called the STL [Stepanov,1994], is extensible so users can add their own containers and algorithms.

  • Ranges (§14.1), including views (§14.2), generators (§14.3), and pipes (§14.4).

  • Concepts for fundamental types and ranges (§14.5).

  • Support for numerical computation, such as standard mathematical functions, complex numbers, vectors with arithmetic operations, mathematical constants, and random-number generators (§5.2.1 and Chapter 16).

  • Support for concurrent programming, including threads and locks (Chapter 18). The concurrency support is foundational so that users can add support for new models of concurrency as libraries.

  • Synchronous and asynchronous coroutines (§18.6).

  • Parallel versions of most STL algorithms and of some numerical algorithms, such as sort()13.6) and reduce()17.3.1).

  • Utilities to support metaprogramming (e.g., type functions; §16.4), STL-style generic programming (e.g., pair; §15.3.3), and general programming (e.g., variant and optional; §15.4.1, §15.4.2).

  • “Smart pointers” for resource management (e.g., unique_ptr and shared_ptr; §15.2.1).

  • Special-purpose containers, such as array15.3.1), bitset15.3.2), and tuple15.3.3).

  • Support for absolute time and durations, e.g., time_point and system_clock16.2.1).

  • Support for calendars, e.g., month and time_zone16.2.2, §16.2.3).

  • Suffixes for popular units, such as ms for milliseconds and i for imaginary (§6.6).

  • Ways of manipulating sequences of elements, such as views (§14.2), string_views (§10.3), and spans (§15.2.2).

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.

  • Simple uses should be easy to learn (relative to the inherent complexity of their task).

Essentially, the C++ standard library provides the most common fundamental data structures together with the fundamental algorithms used on them.

9.3 Standard-Library Organization

The facilities of the standard library are placed in namespace std and made available to users through modules or headed files.

9.3.1 Namespaces

Every standard-library facility is provided through some standard header. For example:

#include<string>
#include<list>

This makes the standard string and list available.

The standard library is defined in a namespace (§3.3) called std. To use standard-library facilities, the std:: prefix can be used:

std::string sheep {"Four legs Good; two legs Baaad!"};
std::list<std::string> slogans {"War is Peace", "Freedom is Slavery", "Ignorance is Strength"};

For brevity, I rarely use the std:: prefix in examples. Neither do I #include or import the necessary headers or modules explicitly. To compile and run the program fragments here, you must make the relevant parts of the standard library available. For example:

#include<string>                     // make the standard string facilities accessible
using namespace std;            // make std names available without std:: prefix

string s {"C++ is a general-purpose programming language"};      // OK: string is std::string

It is generally in poor taste to dump every name from a namespace into the global namespace. However, in this book, I use the standard library exclusively and it is good to know what it offers.

The standard library offers several sub-namespaces to std that can be accessed only through an explicit action:

  • std::chrono: all facilities from chrono, including std::literals::chrono_literals16.2).

  • std::literals::chrono_literals: suffixes y for years, d for days, h for hours, min for minutes, ms for milliseconds, ns for nanoseconds, s for seconds, and us for microseconds (§16.2).

  • std::literals::complex_literals: suffixes i for imaginary doubles, if for imaginary floats, and il for imaginary long doubles (§6.6).

  • std::literals::string_literals: suffix s for strings (§6.6, §10.2).

  • std::literals::string_view_literals: suffix sv for string views (§10.3).

  • std::numbers for mathematical constants (§17.9).

  • std::pmr for polymorphic memory resources (§12.7).

To use a suffix from a sub-namespace, we have to introduce it into the namespace in which we want to use it. For example:

// no mention of complex_literals
auto z1 = 2+3i;          // error: no suffix 'i'

using namespace literals::complex_literals; // make the complex literals visible
auto z2 = 2+3i;          // ok: z2 is a complex<double>

There is no coherent philosophy for what should be in a sub-namespace. However, suffixes cannot be explicitly qualified so we can only bring in a single set of suffixes into a scope without risking ambiguities. Therefore suffixes for a library meant to work with other libraries (that might define their own suffixes) are placed in sub-namespaces.

9.3.2 The ranges namespace

The standard-library offers algorims, such as sort() and copy(), in two versions:

  • A traditional sequence version taking a pair of iterators; e.g., sort(begin(v),v.end())

  • A range version taking a single range; e.g., sort(v)

Ideally, these two versions should overload perfectly without any special effort. However, they don’t. For example:

using namespace std;
using namespace ranges;

void f(vector<int>& v)
{
        sort(v.begin(),v.end());       // error:ambiguous
        sort(v);                                // error: ambiguous
}

To protect against ambiguities when using traditional unconstrained templates, the standard requires that we explicitly introduce the range version of a standard-library algorithm into a scope:

using namespace std;

void g(vector<int>& v)
{
        sort(v.begin(),v.end());     // OK
        sort(v);                              // error: no matching function (in std)
        ranges::sort(v);               // OK
        using ranges::sort;         // sort(v) OK from here on
        sort(v);                             // OK
}

9.3.3 Modules

There are not yet any standard-library modules. C++23 is likely to remedy this omission (caused by lack of committee time). For now, I use module std that is likely to become standard, offering all facilities from namespace std. See Appendix A.

9.3.4 Headers

Here is a selection of standard-library headers, all supplying declarations in namespace std:

Selected Standard Library Headers

<algorithm>

copy(), find(), sort()

Chapter 13

<array>

array

§15.3.1

<chrono>

duration, time_point, month, time_zone

§16.2

<cmath>

sqrt(), pow()

§17.2

<complex>

complex, sqrt(), pow()

§17.4

<concepts>

floating_point, copyable, predicate, invocable

§14.5

<filesystem>

path

§11.9

<format>

format()

§11.6.2

<fstream>

fstream, ifstream, ofstream

§11.7.2

<functional>

function, greater_equal, hash, range_value_t

Chapter 16

<future>

future, promise

§18.5

<ios>

hex, dec, scientific, fixed, defaultfloat

§11.6.2

<iostream>

istream, ostream, cin, cout

Chapter 11

<map>

map, multimap

§12.6

<memory>

unique_ptr, shared_ptr, allocator

§15.2.1

<random>

default_random_engine, normal_distribution

§17.5

<ranges>

sized_range, subrange, take(), split(), iterator_t

§14.1

<regex>

regex, smatch

§10.4

<string>

string, basic_string

§10.2

<string_view>

string_view

§10.3

<set>

set, multiset

§12.8

<sstream>

istringstream, ostringstream

§11.7.3

<stdexcept>

length_error, out_of_range, runtime_error

§4.2

<tuple>

tuple, get<>(), tuple_size<>

§15.3.4

<thread>

thread

§18.2

<unordered_map>

unordered_map, unordered_multimap

§12.6

<utility>

move(), swap(), pair

Chapter 16

<variant>

variant

§15.4.1

<vector>

vector

§12.2

This listing is far from complete.

Headers from the C standard library, such as <stdlib.h> are provided. For each such header there is also a version with its name prefixed by c and the .h removed. This version, such as <cstdlib> places its declarations in both the std and global namespace.

The headers reflect the history of the development of the standard library. Consequently, they are not always as logical and easy to remember as we would like. That’s one reason to use a module, such as std9.3.3), instead.

9.4 Advice

[1] Don’t reinvent the wheel; use libraries; §9.1; [CG: SL.1.]

[2] When you have a choice, prefer the standard library over other libraries; §9.1; [CG: SL.2].

[3] Do not think that the standard library is ideal for everything; §9.1.

[4] If you don’t use modules, remember to #include the appropriate headers; §9.3.1.

[5] Remember that standard-library facilities are defined in namespace std; §9.3.1; [CG: SL.3].

[6] When using ranges, remember to explicitly qualify algorithm names; §9.3.2.

[7] Prefer importing modules over #includeing header files (§9.3.3).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.126.242