# Chapter 17. Specialized Library Facilities
## 17.1 The tuple Type
A tuple is a template that is similar to a pair. Each pair type has different types for its members, but every pair always has exactly two members. A tuple is most useful when we want to combine some data into a single object but do not want to bother to define a data structure to represent those data.
### 17.1.1 Defining and Initializing tuples
When we create a tuple object, we can use the default tuple constructor, which value initializes.
```cpp
tuple<size_t, size_t, size_t> threeD = {1, 2, 3}; // error
tuple<size_t, size_t, size_t> threeD{1, 2, 3}; // ok
```
The library defines a `make_tuple` function that generates a tuple object:
```cpp
auto item = make_tuple("0-999-78345-X", 3, 20.00);
```
| Operations on tuples | |
| ------------------------------------------- | ------------------------------------------------------------ |
| tuple<T1, T2, ..., Tn> t; | t is a tuple with as many members as there are type T1 ...Tn. The member is value initialized. |
| tuplte<T1, T2, ..., Tn> t(v1, v2, ..., vn); | t is a tuple with types T1 ... Tn in which each member is initialized from the corresponding initializer, vi. This constructor is explicit. |
| make_tuple(v1, v2, ..., vn); | Returns a tuple initialized from the given initializers. |
| get<i>(t) | Returns a reference to the with data member of t; if t is an lvalue, the result is an lvalue reference; otherwise, it is an rvalue reference. |
| tuple_size<tupleType>::value | A class template that can be instantiated by a tuple type and has a public constexpr static data member named value of type size_t that is the number of members in the specified tuple type. |
| tuple_element<i, tupleType>::type | A class template that can be instantiated by an integral constant and a tuple type and has a public member named type that is the type of the specified members in the specified tuple type. |
We access the members of a tuple through a library function template named get.
```c++
auto book = get<0>(item);
auto cnt = get<1>(item);
auto price = get<2>(item)/cnt;
get<2>(item) *= 0.8;
```
The value inside the brackets must be an integral constant expression. As usual, we count from 0, meaning that `get<0>` is the first member.
```
typedef decltype(item) trans; // trans is the type of item;
size_t sz = tuple_size<trans>::value; // returns 3
tuple_element<1, trans>::type cnt = get<1>(item);
```
We can compare two tuples only if they have the same number of members.
### 17.1.2 Using a tuple to Return Multiple Values
A common use of tuple is to return multiple values from a function.
## 17.2 The bitset Type
The standard library defines the bites class to make it easier to use bit operations and possible to deal with collections of bits that are larger than the longest integral type. The bitset class is defined in the bitset header.
### 17.2.1 Defining and Initializing bitsets
The bitset class is a class template that, like the array class, has a fixed size. When we define a bitset, we say how many bits the bitset contain:
```c++
bitset<32> bitvec(1U);
```
The bits starting at 0 are referred to as the low-order bits, and those ending at 31 are referred to as high-order bits.
### 17.2.2 Operations on bitsets
These operations throw an `overflow_error` exception if the value in the bitset does not fit in the specified type.
## 17.3 Regular Expressions
A regular expression is a way of describing a sequence of characters. The regex class represents a regular expression.
The function `regex_match`and `regex_search` determine whether a given character sequence matches a given regex. The `regex_match`function returns true if the entire input sequence matches the expression; `regex_search`returns true if there is a substring in the input sequence that matches.
### 17.3.1 Using the Regular Expression Library
The regular expression `[^c]` says we want any character that is not a `c`, and `[^c]ei` says we want any such letter that is followed by the letter `ei`.
`[[:alpha:]]*` will match zero or more characters.
```cpp
regex r("[[:alnum:]]+\\.(cpp|cxx|cc)$", regex::icase);
```
We must write `\\.` to represent a regular expression that will match a period.
It is important to realize that the syntactic correctness of a regular expression is evaluated at run time.
If we make a mistake in writing a regular expression, then at run time the library will throw an exception of type `regex_error`.
```cpp
try {
regex r("[[:alnum:]]+\\.(cpp|cxx|cc)$", regex::icase);
} catch (regex_error e) {
cout << e.what() << "\ncode: " << e.code() << endl;
}
```
The "program" that a regular expression represents is compiled at run time, not at compile time. Compiling a regular expression can be a surprisingly slow operation, especially if you're using the extended regular-expression grammar or are using a complicated expression.
### 17.3.2 The Match and Regex Iterator Types
We can get all the matches by using an `sregex_iterator`. The regex iterators are iterator adaptors that are bound to an input sequence and a regex object.
```cpp
for (sregex_iterator it(file.begin(), file.end(), r), end_it; it != end_it; ++it) {}
```
### 17.3.3 Using Subexpressions
A pattern in a regular expression often contain s one or more subexpressions. A subexpression is a part of the pattern that itself has meaning. Regular-expression grammars typically use parentheses to denote subexpressions.
```cpp
regex r("([[:alnum:]]+)\\.(cpp|cxx|cc)$", regex::icase);
// ([[:alnum:]]+), which is a sequence of one or more characters.
// (cpp|cxx|cc), which is the file extension
```
### 17.3.4 Using regex_replace
When we want to find and replace a regular expression in the input sequence, we call `regex_replace`
```cpp
string fmt = "$2.$5.%7";
regex r(phone);
stirng number = "(908) 555-1800";
cout << regex_replace(number, r, fmt) << endl;
// 908.555.1800
```
These flags can be passed to the `regex_search` or `regex_match` functions or to the format numbers of class `smatch`.
## 17.4 Random Numbers
Prior to the new standard, both C and C++ relied on a simple C library function name `rand`. The `rand` function has several problems: Many, if not most, programs need random numbers in a different range from the one produced by `rand`. Some applications require random floating-point numbers. Some programs need numbers that reflect a non-uniform distribution.
The random-number library, defined in the `random` header, solves these problems through a set of cooperating classes: random-number engines and random-number distribution classes.
### 17.4.1 Random-Number Engines and Distribution
We can generate raw random numbers by clling an object of a random-number engine type:
```cpp
default_random_engine e;
cout << e() << std::endl;
```
To get a number in a specified range, we use an object of a distribution type:
```cpp
uniform_int_distribution<unsigned> u(0, 9);
default_random_engine e;
cout << u(e) << std::endl;
```
The range for `rand` is 0 to `RAND_MAX`. The range for an engine type is returned by calling the `min` and `max` members on an object of that type.
Even though the numbers that are generated appear to be random, a given generator returns the same sequence of numbers each time it is run.
```cpp
vector<unsigned> bad_randVec() {
default_random_engine e;
uniform_int_distribution<unsigned> u(0, 9);
vector<unsigned> ret;
for (size_t i = 0; i < 100; ++i) {
ret.push_back(u(e));
}
return ret;
}
vector<unsigned> bad_randVec() {
static default_random_engine e;
static uniform_int_distribution<unsigned> u(0, 9);
vector<unsigned> ret;
for (size_t i = 0; i < 100; ++i) {
ret.push_back(u(e));
}
return ret;
}
```
A given random-number generator always produces the same sequence of numbers A function with a local random-number generator should make that generator static.
A seed is a value that an engine can use to case it to start generating numbers at a new point in its sequence.
```cpp
default_random_engine e1; // use the default seed
default_random_engine e2(2147483646); // use the given seed value
default_random_engine e3(time(0)); // a somewhat random seed
```
Using time as a seed usually doesn't work if the program is run repeatedly as part of an automated process; it might wind up with the same seed several times.
### 17.4.2 Other Kinds of Distributions
We define an object of type `uniform_real_distribution` and let the library handle mapping random integers to random floating-point numbers.
```cpp
default_random_engine e;
uniform_real_distribution<double> u(0, 1);
cout << u(e) << std::endl;
```
The distribution types that generate floating-point value generate double by default.
```cpp
uniform_real_distribution<> u(0, 1);
```
`normal_distribution` generates floating-point numbers, our program will use the `lround` function from the `cmatch` header to round each result to its nearest integer.
```cpp
default_random_engine e;
normal_distribution<> n(4, 1.5);
unsigned v = lround(n(e));
```
That distribution is the `bernoulli_distribution`, which is an ordinary class, not a template. This distribution always returns a bool value. It returns true with a given probability.
```cpp
bernoulli_distribution b(.55);
```
## 17.5 The IO Library Revisited
### 17.5.1 Formatted Input and Output
The library defines a set of manipulators, that modify the format state of a stream.
Manipulators that change the format state of the stream usually leave the format state changed for all subsequent IO.
The `hex`, `oct`, and `dec` manipulators affect only integral operands; the representation of floating-point values is unaffected.
The showcase manipulator causes the output stream to use the same conventions as used for specifying the base of an integral constant:
* A leading 0x indicates hexadecimal.
* A leading 0 indicates octal.
* The absence of either indicates decimal.
The `setprecision` manipulators and other manipulators that take arguments are defined in the `iomanip` header.
```cpp
cout << "Precision: " << cout.precision() << ", Value: " << sqrt(2.0) << std::endl;
cout.precision(12);
cout << setprecision(3);
```
The `scientific` manipulator changes the stream to use scientific notation. The `fixed` manipulator changes the stream to use fixed decimal.
Under the new library, we can also force floating-point values to use hexadecimal format by using `hexfloat`. The new library provides another manipulator, named `defaultfloat`. This manipulator returns the stream to its default state in which it chooses a notation based on the value being printed.
Be default, when the fractional part a floating-point value is 0, the decimal point is not displayed. The `showpoint` manipulator forces the decimal point to be printed:
```cpp
cout << showpoint << 10.0 << noshowpoint << endl;
```
* `setw` to specify the minimum space for the next numeric or string value.
* `left` to left-justify the output.
* `right` to right-justify the output. Output is right-justified by default.
* `internal` control the placement of the sign on a negative value.
* `setfill` lets us specify an alternative character to use to pad the output. Be default, the value is a space.
Be default, the input operators ignore whitespace(blank, tab, newline, formed, and carriage return).
The `noskipws` manipulator causes the input operator to read, rather than skip, whitespace.
```cpp
cin >> noskipws;
```
### 17.5.2 Unformatted Input/Output Operations
| Single-Byte Low-Level IO Operations | |
| ----------------------------------- | ------------------------------------------------------ |
| is.get(ch); | Put the next byte from the istream is in character ch. |
| os.put(ch); | Put the character ch onto the ostream os. |
| is.get(); | Returns next byte from is as an int. |
| is.putback(ch); | Put the character ch back on is. |
| Is.unget(); | Move is back one byte. |
| is.peek(); | Return the next the as an int but doesn't remove it. |
### 17.5.3 Random Access to a Stream
Because the `istream` and `ostream` types usually do not support random access, the remainder of this section should be considered as applicable to only the `fstream` and `sstream` type.
```cpp
ostringstream writeStr;
ostringstream::pos_type mark = writeStr.tellp();
if (cancelEntry)
writeStr.seekp(mark);
```
- Introduction
- Chapter 1. Getting Start
- Chapter 2. Variables and Basic Types
- Chapter 3. String, Vectors, and Arrays
- Chapter 4. Expressions
- Chapter 5. Statements
- Chapter 6. Functions
- Chapter 7. Classes
- Chapter 8. The IO Library
- Chapter 9. Sequential Containers
- Chapter 10. Generic Algorithms
- Chapter 11. Associative Container
- Chapter 12. Dynamic Memory
- Chapter 13. Copy Control
- Chapter 14. Overloaded Operations and Conversions
- Chapter 15. Object-Oriented Programming
- Chapter 16. Template Argument Deduction
- Chapter 17. Specialized Library Facilities
- Chapter 18. Tools for Large Programs
- Chapter 19. Specialized Tools and Techniques
