listings-Chap28-README-onepage.md
Listings of Chap28.docx
This is the list of listings on one page. You can also view a linked summary.
Listing 28.1: How to return two values simultaneously using “pair”.
Book listing lst-0001-book.cpp:
// https://godbolt.org/z/4YM9d99xG
#include <iostream>
#include <string>
#include <vector>
#include <utility> // pair
using std::pair; using std::cout; using std::cin; using std::string;
std::vector<string> months { "Jan", "Feb", "Mar" };
std::vector temps { 8, 12, 11 };
std::pair<string, int> monthWithTemp(size_t m) {
auto month = months.at(m);
auto temperature = temps.at(m);
return std::make_pair(month, temperature);
}
int main() {
std::pair data = monthWithTemp(1);
cout << "Month : " << data.first << std::endl; // Output: Month : Feb
cout << "Temperature : " << data.second << std::endl;
// Output: Temperature : 12
}
Godbolt Listing lst-0001-godb.cpp, https://godbolt.org/z/4YM9d99xG:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4YM9d99xG
#include <iostream>
#include <string>
#include <vector>
#include <utility> // pair
using std::pair; using std::cout; using std::cin; using std::string;
std::vector<string> months { "Jan", "Feb", "Mar" };
std::vector temps { 8, 12, 11 };
std::pair<string, int> monthWithTemp(size_t m) {
auto month = months.at(m);
auto temperature = temps.at(m);
return std::make_pair(month, temperature);
}
int main() {
std::pair data = monthWithTemp(1);
cout << "Month : " << data.first << std::endl; // Output: Month : Feb
cout << "Temperature : " << data.second << std::endl;
// Output: Temperature : 12
}
Listing 28.2: With “tuple”, you can return any number of elements.
Book listing lst-0002-book.cpp:
// https://godbolt.org/z/5z4s6WMxG
#include <iostream>
#include <string>
#include <algorithm> // min, max
#include <tuple>
using std::tuple; using std::make_tuple; using std::get; using std::cout;
using std::string;
tuple<int,int,int> arrange(int a, int b, int c) {
using std::min; using std::max;
auto x = min(a,min(b,c));
auto y = max(min(a,b), min(max(a,b),c));
auto z = max(a,max(b,c));
return make_tuple(x, y, z);
}
auto president(int year) {
using namespace std::literals;
if(year >= 2021)
return std::make_tuple("Joseph"s, "Biden"s, "Democratic"s, 1942);
if(year >= 2017)
return std::make_tuple("Donald"s, "Trump"s, "Republican"s, 1946);
if(year >= 2009)
return std::make_tuple("Barack"s, "Obama"s, "Democratic"s, 1961);
// Add more presidents as needed...
return std::make_tuple(""s, ""s, ""s, 0); // Default case
}
int main() {
tuple<int,int,int> zs = arrange(23, 42, 7);
cout << get<0>(zs) <<' '<< get<1>(zs) <<' '<< get<2>(zs) <<'\n';
// Output: 7 23 42
auto ps = president(2015);
cout << get<1>(ps) << '\n'; // Output: Obama
}
Godbolt Listing lst-0002-godb.cpp, https://godbolt.org/z/5z4s6WMxG:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/5z4s6WMxG
#include <iostream>
#include <string>
#include <algorithm> // min, max
#include <tuple>
using std::tuple; using std::make_tuple; using std::get; using std::cout;
using std::string;
tuple<int,int,int> arrange(int a, int b, int c) {
using std::min; using std::max;
auto x = min(a,min(b,c));
auto y = max(min(a,b), min(max(a,b),c));
auto z = max(a,max(b,c));
return make_tuple(x, y, z);
}
auto president(int year) {
using namespace std::literals;
if(year >= 2021)
return std::make_tuple("Joseph"s, "Biden"s, "Democratic"s, 1942);
if(year >= 2017)
return std::make_tuple("Donald"s, "Trump"s, "Republican"s, 1946);
if(year >= 2009)
return std::make_tuple("Barack"s, "Obama"s, "Democratic"s, 1961);
// Add more presidents as needed...
return std::make_tuple(""s, ""s, ""s, 0); // Default case
}
int main() {
tuple<int,int,int> zs = arrange(23, 42, 7);
cout << get<0>(zs) <<' '<< get<1>(zs) <<' '<< get<2>(zs) <<'\n';
// Output: 7 23 42
auto ps = president(2015);
cout << get<1>(ps) << '\n'; // Output: Obama
}
Listing 28.3: “get” works with a type as an index.
Book listing lst-0003-book.cpp:
// https://godbolt.org/z/TE1EcEYPv
// … as before …
int main() {
tuple ps = president(2015);
cout << get<int>(ps) << '\n'; // Output: 1940
cout << get<string>(ps) << '\n'; // (ERR) not unique
}
Godbolt Listing lst-0003-godb.cpp, https://godbolt.org/z/TE1EcEYPv:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/TE1EcEYPv
// … as before …
int main() {
tuple ps = president(2015);
cout << get<int>(ps) << '\n'; // Output: 1940
cout << get<string>(ps) << '\n'; // (ERR) not unique
}
Listing 28.4: Decomposing tuples with “tie” and “ignore”.
Book listing lst-0004-book.cpp:
// https://godbolt.org/z/zG7zYGf3K
// … as before …
int main() {
using std::tie; using std::ignore;
string lastName {};
int birthYear {};
tie(ignore, lastName, ignore, birthYear) = president(2015);
cout << lastName << ' ' << birthYear << '\n'; // Output: Obama 1961
}
Godbolt Listing lst-0004-godb.cpp, https://godbolt.org/z/zG7zYGf3K:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/zG7zYGf3K
// … as before …
int main() {
using std::tie; using std::ignore;
string lastName {};
int birthYear {};
tie(ignore, lastName, ignore, birthYear) = president(2015);
cout << lastName << ' ' << birthYear << '\n'; // Output: Obama 1961
}
Listing 28.5: Tuples implement lexicographical order.
Book listing lst-0005-book.cpp:
// https://godbolt.org/z/sG4E66YhW
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
#include <algorithm> // ranges::sort
using std::tuple; using std::get; using std::cout; using std::string;
int main() {
std::vector<tuple<string,string,int>> armstrongs =
{ {"Armstrong", "Louis", 1901} // Initialize using initializer list
, {"Armstrong", "Lance", 1971}
, {"Armstrong", "Neil", 1930} };
std::ranges::sort(armstrongs); // Lance < Louis < Neil
for(const auto& a : armstrongs) {
cout << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a) << "\n";
}
}
Godbolt Listing lst-0005-godb.cpp, https://godbolt.org/z/sG4E66YhW:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/sG4E66YhW
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
#include <algorithm> // ranges::sort
using std::tuple; using std::get; using std::cout; using std::string;
int main() {
std::vector<tuple<string,string,int>> armstrongs =
{ {"Armstrong", "Louis", 1901} // Initialize using initializer list
, {"Armstrong", "Lance", 1971}
, {"Armstrong", "Neil", 1930} };
std::ranges::sort(armstrongs); // Lance < Louis < Neil
for(const auto& a : armstrongs) {
cout << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a) << "\n";
}
}
Listing 28.6: Tuples as keys.
Book listing lst-0006-book.cpp:
// https://godbolt.org/z/9qhMo6zbb
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>
using std::tuple; using std::get; using std::cout; using std::string;
int main() {
std::map<tuple<int,string>,double> m { {{12,"x"},3.14} };
cout << m[{12,"x"}] << "\n"; // Output: 3.14
std::unordered_set<tuple<int,string>> s { {12,"x"} }; // (ERR) no std::hash
}
Godbolt Listing lst-0006-godb.cpp, https://godbolt.org/z/9qhMo6zbb:
//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9qhMo6zbb
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>
using std::tuple; using std::get; using std::cout; using std::string;
int main() {
std::map<tuple<int,string>,double> m { {{12,"x"},3.14} };
cout << m[{12,"x"}] << "\n"; // Output: 3.14
std::unordered_set<tuple<int,string>> s { {12,"x"} }; // (ERR) no std::hash
}
Listing 28.7: Forming tuples in-place using tie.
Book listing lst-0007-book.cpp:
// https://godbolt.org/z/vdT7TTjWK
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>
using std::tuple; using std::tie; using std::cout; using std::string;
struct Point {
int x,y,z;
bool operator<(const Point &b) {
return tie(x,y,z) < tie(b.x, b.y, b.z);
}
};
int main() {
Point a{ 11, 22, 33 };
Point b{ 11, 33, 0 };
cout << std::boolalpha << (a < b) << "\n"; // Output: true
}
Godbolt Listing lst-0007-godb.cpp, https://godbolt.org/z/vdT7TTjWK:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vdT7TTjWK
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>
using std::tuple; using std::tie; using std::cout; using std::string;
struct Point {
int x,y,z;
bool operator<(const Point &b) {
return tie(x,y,z) < tie(b.x, b.y, b.z);
}
};
int main() {
Point a{ 11, 22, 33 };
Point b{ 11, 33, 0 };
cout << std::boolalpha << (a < b) << "\n"; // Output: true
}
Listing 28.8: Combining several small tuples into one large tuple.
Book listing lst-0008-book.cpp:
// https://godbolt.org/z/eq1dqWbe9
#include <iostream>
#include <string>
#include <tuple>
using std::tuple; using std::cout; using std::string;
int main() {
tuple<int,string> a { 12, "gnorf" };
tuple b { 666 };
tuple<double,double,string> c { 77.77, 33.33, "frong" };
tuple<int,string,int,double,double,string> r = std::tuple_cat( a, b, c );
cout << std::get<2>(r) << "\n"; // Output: 666
}
Godbolt Listing lst-0008-godb.cpp, https://godbolt.org/z/eq1dqWbe9:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eq1dqWbe9
#include <iostream>
#include <string>
#include <tuple>
using std::tuple; using std::cout; using std::string;
int main() {
tuple<int,string> a { 12, "gnorf" };
tuple b { 666 };
tuple<double,double,string> c { 77.77, 33.33, "frong" };
tuple<int,string,int,double,double,string> r = std::tuple_cat( a, b, c );
cout << std::get<2>(r) << "\n"; // Output: 666
}
Listing 28.9: Useful tuple type traits.
Book listing lst-0009-book.cpp:
// https://godbolt.org/z/Psdz9s9Gc
#include <iostream>
#include <string>
#include <tuple>
using namespace std;
template<typename Tuple>
auto back(Tuple &&tuple) {
using Noref = typename remove_reference<Tuple>::type; // in case of Tuple&
constexpr auto sz = tuple_size<Noref>::value;
return get<sz-1>(forward<Tuple>(tuple));
}
int main() {
tuple<string,int,string> enterprise = make_tuple("NCC", 1701, "D");
cout << back(enterprise) << "\n"; // Output: D
}
Godbolt Listing lst-0009-godb.cpp, https://godbolt.org/z/Psdz9s9Gc:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Psdz9s9Gc
#include <iostream>
#include <string>
#include <tuple>
using namespace std;
template<typename Tuple>
auto back(Tuple &&tuple) {
using Noref = typename remove_reference<Tuple>::type; // in case of Tuple&
constexpr auto sz = tuple_size<Noref>::value;
return get<sz-1>(forward<Tuple>(tuple));
}
int main() {
tuple<string,int,string> enterprise = make_tuple("NCC", 1701, "D");
cout << back(enterprise) << "\n"; // Output: D
}
Listing 28.10: Matching, searching, and enumerating with regular expressions.
Book listing lst-0010-book.cpp:
// https://godbolt.org/z/T1YMoM5as
#include <string>
#include <iostream>
#include <regex>
using std::regex; using std::sregex_iterator; using std::string;
const regex rgxMobile(R"(01[567]\d{6,10})"); // Mobile phone 0151-0179
bool isMobilephone(const string& text) {
return std::regex_match(text, rgxMobile); // Does the text match completely?
}
bool containsMobilephone(const string &text) {
return std::regex_search(text, rgxMobile); // somewhere in the text?
}
void listMobilephones(const string &text) {
sregex_iterator begin{ text.cbegin(), text.cend(), rgxMobile };
sregex_iterator end;
for(auto it = begin; it != end; ++it)
std::cout << it->str() << " "; // Matched text
} // "xyz01709999 abc 0161887766 uvw" -> "0161887766"
Godbolt Listing lst-0010-godb.cpp, https://godbolt.org/z/T1YMoM5as:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/T1YMoM5as
#include <string>
#include <iostream>
#include <regex>
using std::regex; using std::sregex_iterator; using std::string;
const regex rgxMobile(R"(01[567]\d{6,10})"); // Mobile phone 0151-0179
bool isMobilephone(const string& text) {
return std::regex_match(text, rgxMobile); // Does the text match completely?
}
bool containsMobilephone(const string &text) {
return std::regex_search(text, rgxMobile); // somewhere in the text?
}
void listMobilephones(const string &text) {
sregex_iterator begin{ text.cbegin(), text.cend(), rgxMobile };
sregex_iterator end;
for(auto it = begin; it != end; ++it)
std::cout << it->str() << " "; // Matched text
} // "xyz01709999 abc 0161887766 uvw" -> "0161887766"
Listing 28.11: Search and match.
Book listing lst-0011-book.cpp:
// https://godbolt.org/z/E9hcWGMW4
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_match; using std::regex_search;
int main() {
std::cout << std::boolalpha;
regex pattern {"ello"};
std::string text = "Hello world";
auto b1 = regex_match (text.cbegin(), text.cend(), pattern); // does’t match
std::cout << b1 << "\n"; // Output: false
auto b2 = regex_search(text.cbegin(), text.cend(), pattern); // found
std::cout << b2 << "\n"; // Output: true
}
Godbolt Listing lst-0011-godb.cpp, https://godbolt.org/z/E9hcWGMW4:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/E9hcWGMW4
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_match; using std::regex_search;
int main() {
std::cout << std::boolalpha;
regex pattern {"ello"};
std::string text = "Hello world";
auto b1 = regex_match (text.cbegin(), text.cend(), pattern); // does’t match
std::cout << b1 << "\n"; // Output: false
auto b2 = regex_search(text.cbegin(), text.cend(), pattern); // found
std::cout << b2 << "\n"; // Output: true
}
Listing 28.12: Accessing the match details.
Book listing lst-0012-book.cpp:
// https://godbolt.org/z/Yzefv59en
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
int main() {
cmatch res; // for detailed results
std::string text = "<h2>Result and parts of it</h2>";
regex pattern{"<h(.)>([^<]+)"}; // Search pattern with groups
regex_search(text.c_str(), res, pattern); // Details to res
std::cout << res[1] << ". " // ()-Group 1: H-Level
<< res[2] << std::endl; // ()-Group 2: H-Text
}
Godbolt Listing lst-0012-godb.cpp, https://godbolt.org/z/Yzefv59en:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/Yzefv59en
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
int main() {
cmatch res; // for detailed results
std::string text = "<h2>Result and parts of it</h2>";
regex pattern{"<h(.)>([^<]+)"}; // Search pattern with groups
regex_search(text.c_str(), res, pattern); // Details to res
std::cout << res[1] << ". " // ()-Group 1: H-Level
<< res[2] << std::endl; // ()-Group 2: H-Text
}
Listing 28.13: Replace matches with new text.
Book listing lst-0013-book.cpp:
// https://godbolt.org/z/rErP43G89
#include <regex>
#include <string>
#include <iostream>
using std::string;
int main() {
string text = "Title;Album;Artist";
std::regex pattern{";"};
string new_str = std::regex_replace(text, pattern, string{","});
std::cout << new_str << "\n"; // Output: Title,Album,Artist
}
Godbolt Listing lst-0013-godb.cpp, https://godbolt.org/z/rErP43G89:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rErP43G89
#include <regex>
#include <string>
#include <iostream>
using std::string;
int main() {
string text = "Title;Album;Artist";
std::regex pattern{";"};
string new_str = std::regex_replace(text, pattern, string{","});
std::cout << new_str << "\n"; // Output: Title,Album,Artist
}
Listing 28.14: Hard to maintain regular expression.
Book listing lst-0016-book.cpp:
// https://godbolt.org/z/dG5vE3heM
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
const regex pattern{R"(^score\s+(\d+)\s+for\s+(\d+)\s+nights?\s+at\s+(.*))"};
void extract(const std::string &text) {
cmatch res;
regex_search(text.c_str(), res, pattern);
std::cout << res[1] << "," << res[2] << "," << res[3] << "\n";
}
int main() {
extract("score 400 for 2 nights at Minas Tirith Airport");
extract("score 84 for 1 night at Prancing Pony");
}
Godbolt Listing lst-0016-godb.cpp, https://godbolt.org/z/dG5vE3heM:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/dG5vE3heM
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
const regex pattern{R"(^score\s+(\d+)\s+for\s+(\d+)\s+nights?\s+at\s+(.*))"};
void extract(const std::string &text) {
cmatch res;
regex_search(text.c_str(), res, pattern);
std::cout << res[1] << "," << res[2] << "," << res[3] << "\n";
}
int main() {
extract("score 400 for 2 nights at Minas Tirith Airport");
extract("score 84 for 1 night at Prancing Pony");
}
Listing 28.15: Name parts and then combine them.
Book listing lst-0017-book.cpp:
// https://godbolt.org/z/TK6n4dG37
const string scoreKeyword = R"(^score\s+)";
const string numberOfPoints = R"((\d+))";
const string forKeyword = R"(\s+for\s+)";
const string numberOfNights = R"((\d+))";
const string nightsAtKeyword = R"(\s+nights?\s+at\s+)";
const string hotelName = R"((.*))";
const regex pattern{ scoreKeyword + numberOfPoints +
forKeyword + numberOfNights + nightsAtKeyword + hotelName };
}
Godbolt Listing lst-0017-godb.cpp, https://godbolt.org/z/TK6n4dG37:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TK6n4dG37
const string scoreKeyword = R"(^score\s+)";
const string numberOfPoints = R"((\d+))";
const string forKeyword = R"(\s+for\s+)";
const string numberOfNights = R"((\d+))";
const string nightsAtKeyword = R"(\s+nights?\s+at\s+)";
const string hotelName = R"((.*))";
const regex pattern{ scoreKeyword + numberOfPoints +
forKeyword + numberOfNights + nightsAtKeyword + hotelName };
}
Listing 28.16: Commenting within the expression.
Book listing lst-0018-book.cpp:
// https://godbolt.org/z/MszTjE3dv
const regex pattern{R"(^score)"
R"(\s+)"
R"((\d+))" // points
R"(\s+)"
R"(for)"
R"(\s+)"
R"((\d+))" // number of nights
R"(\s+)"
R"(night)"
R"(s?)" // optional: plural
R"(\s+)"
R"(at)"
R"(\s+)"
R"((.*))" // hotel name
R"()"};
Godbolt Listing lst-0018-godb.cpp, https://godbolt.org/z/MszTjE3dv:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MszTjE3dv
const regex pattern{R"(^score)"
R"(\s+)"
R"((\d+))" // points
R"(\s+)"
R"(for)"
R"(\s+)"
R"((\d+))" // number of nights
R"(\s+)"
R"(night)"
R"(s?)" // optional: plural
R"(\s+)"
R"(at)"
R"(\s+)"
R"((.*))" // hotel name
R"()"};
Listing 28.17: This is how you get a uniformly distributed random number between two bounds.
Book listing lst-0019-book.cpp:
// https://godbolt.org/z/ocP83a7ac
#include <random>
#include <vector>
#include <iostream>
void rollDice() {
std::default_random_engine engine{}; // Normal quality randomness
std::vector<size_t> counts{0,0,0,0,0,0};
std::uniform_int_distribution<int> d6{0, 5}; // uniformly distributed integers
for(auto i=1200*1000; i>0; --i)
++counts[d6(engine)];
for(auto c : counts) std::cout<<" "<<c;
std::cout << '\n';
}
int main() {
rollDice();
}
Godbolt Listing lst-0019-godb.cpp, https://godbolt.org/z/ocP83a7ac:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/ocP83a7ac
#include <random>
#include <vector>
#include <iostream>
void rollDice() {
std::default_random_engine engine{}; // Normal quality randomness
std::vector<size_t> counts{0,0,0,0,0,0};
std::uniform_int_distribution<int> d6{0, 5}; // uniformly distributed integers
for(auto i=1200*1000; i>0; --i)
++counts[d6(engine)];
for(auto c : counts) std::cout<<" "<<c;
std::cout << '\n';
}
int main() {
rollDice();
}
Listing 28.18: Speeds of the random number generators.
Book listing lst-0023-book.cpp:
// https://godbolt.org/z/e67356bMq
#include <random>
#include <chrono> // system_clock
#include <format>
#include <iostream>
using namespace std;
using namespace chrono;
const size_t LOOPS = 10*1000*1000;
template<typename ENGINE>
void measure(const string &title, ENGINE &engine) {
const auto start = steady_clock::now();
/* work hard */
unsigned long long checksum = 0;
size_t loops = LOOPS;
while(loops-- > 0)
checksum += engine();
const auto now = steady_clock::now();
nanoseconds dur_ns = now - start;
cout << std::format(" {}: {:5} ns/loop {:12} ns\n",
title, dur_ns.count() / LOOPS, dur_ns.count());
}
int main() {
{ default_random_engine e{}; measure(" default", e ); }
{ random_device e{}; measure(" device", e ); }
{ minstd_rand0 e{}; measure(" minstd_rand0", e ); }
{ minstd_rand e{}; measure(" minstd_rand ", e ); }
{ mt19937 e{}; measure(" mt19937 ", e ); }
{ mt19937_64 e{}; measure(" mt19937_64", e ); }
{ ranlux24_base e{}; measure(" ranlux24_base", e ); }
{ ranlux48_base e{}; measure(" ranlux48_base", e ); }
{ ranlux24 e{}; measure(" ranlux24 ", e ); }
{ ranlux48 e{}; measure(" ranlux48 ", e ); }
{ knuth_b e{}; measure(" knuth_b", e ); }
{
using wide_t = unsigned long long ;
independent_bits_engine<ranlux48, sizeof(wide_t)*8, wide_t> e{};
measure("indep<ranlux> ", e );
}
{
using wide_t = unsigned long long;
independent_bits_engine<
default_random_engine,
sizeof(wide_t)*8, wide_t>
e {};
measure("indep<default>", e );
}
}
Godbolt Listing lst-0023-godb.cpp, https://godbolt.org/z/e67356bMq:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/e67356bMq
#include <random>
#include <chrono> // system_clock
#include <format>
#include <iostream>
using namespace std;
using namespace chrono;
const size_t LOOPS = 10*1000*1000;
template<typename ENGINE>
void measure(const string &title, ENGINE &engine) {
const auto start = steady_clock::now();
/* work hard */
unsigned long long checksum = 0;
size_t loops = LOOPS;
while(loops-- > 0)
checksum += engine();
const auto now = steady_clock::now();
nanoseconds dur_ns = now - start;
cout << std::format(" {}: {:5} ns/loop {:12} ns\n",
title, dur_ns.count() / LOOPS, dur_ns.count());
}
int main() {
{ default_random_engine e{}; measure(" default", e ); }
{ random_device e{}; measure(" device", e ); }
{ minstd_rand0 e{}; measure(" minstd_rand0", e ); }
{ minstd_rand e{}; measure(" minstd_rand ", e ); }
{ mt19937 e{}; measure(" mt19937 ", e ); }
{ mt19937_64 e{}; measure(" mt19937_64", e ); }
{ ranlux24_base e{}; measure(" ranlux24_base", e ); }
{ ranlux48_base e{}; measure(" ranlux48_base", e ); }
{ ranlux24 e{}; measure(" ranlux24 ", e ); }
{ ranlux48 e{}; measure(" ranlux48 ", e ); }
{ knuth_b e{}; measure(" knuth_b", e ); }
{
using wide_t = unsigned long long ;
independent_bits_engine<ranlux48, sizeof(wide_t)*8, wide_t> e{};
measure("indep<ranlux> ", e );
}
{
using wide_t = unsigned long long;
independent_bits_engine<
default_random_engine,
sizeof(wide_t)*8, wide_t>
e {};
measure("indep<default>", e );
}
}
Listing 28.19: A binomial distribution.
Book listing lst-0024-book.cpp:
// https://godbolt.org/z/rv5fWP5Ya
#include <random>
#include <vector>
#include <iostream>
using namespace std;
int main() {
static const size_t size = 10;
default_random_engine e{}; // Random number generator
vector<size_t> counts(size+1);
binomial_distribution<int> coins{size}; // tosses 10 coins, 0 to 10 heads
for(auto i=120*1000; i>0; --i)
++counts[coins(e)]; // Tossing coins
for(auto c : counts) cout<<" "<<c;
cout << '\n';
// Example output:
// 109 1159 5344 14043 24806 29505 24544 13973 5252 1150 115
}
Godbolt Listing lst-0024-godb.cpp, https://godbolt.org/z/rv5fWP5Ya:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/rv5fWP5Ya
#include <random>
#include <vector>
#include <iostream>
using namespace std;
int main() {
static const size_t size = 10;
default_random_engine e{}; // Random number generator
vector<size_t> counts(size+1);
binomial_distribution<int> coins{size}; // tosses 10 coins, 0 to 10 heads
for(auto i=120*1000; i>0; --i)
++counts[coins(e)]; // Tossing coins
for(auto c : counts) cout<<" "<<c;
cout << '\n';
// Example output:
// 109 1159 5344 14043 24806 29505 24544 13973 5252 1150 115
}
Listing 28.20: A “double” random number.
Book listing lst-0025-book.cpp:
// https://godbolt.org/z/94McsP7PG
#include <random>
#include <iostream>
int main() {
std::default_random_engine e{};
std::uniform_real_distribution<double> unif{3,7}; // in the half-open interval [3,7)
double u = unif(e); // Generate random number
std::cout << u << '\n'; // Example output: 3.52615
}
Godbolt Listing lst-0025-godb.cpp, https://godbolt.org/z/94McsP7PG:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/94McsP7PG
#include <random>
#include <iostream>
int main() {
std::default_random_engine e{};
std::uniform_real_distribution<double> unif{3,7}; // in the half-open interval [3,7)
double u = unif(e); // Generate random number
std::cout << u << '\n'; // Example output: 3.52615
}
Listing 28.21: Change generation parameters for each random number individually.
Book listing lst-0026-book.cpp:
// https://godbolt.org/z/xz64qK3e5
#include <random>
#include <iostream>
int main() {
std::default_random_engine e{};
using Dstr = std::uniform_int_distribution<int>; // uniformly distributed int
Dstr card{}; // generate distribution
for(int n=32; n>=1; --n)
std::cout <<" "<< card(e, Dstr::param_type{1,n} ); // parameters only here
std::cout << '\n';
// output for example:
// 1 5 23 14 15 6 2 17 17 22 9 11 17 1 1 10 11 1 6 1 6 8 6 9 7 4 1 4 2 3 2 1
}
Godbolt Listing lst-0026-godb.cpp, https://godbolt.org/z/xz64qK3e5:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xz64qK3e5
#include <random>
#include <iostream>
int main() {
std::default_random_engine e{};
using Dstr = std::uniform_int_distribution<int>; // uniformly distributed int
Dstr card{}; // generate distribution
for(int n=32; n>=1; --n)
std::cout <<" "<< card(e, Dstr::param_type{1,n} ); // parameters only here
std::cout << '\n';
// output for example:
// 1 5 23 14 15 6 2 17 17 22 9 11 17 1 1 10 11 1 6 1 6 8 6 9 7 4 1 4 2 3 2 1
}
GodboltId:173nr4xxd
Book listing lst-0031-book.cpp:
// https://godbolt.org/z/173nr4xxd
sleep(10min);
sleep(std::chrono::minutes{10});
sleep(std::chrono::duration<unsigned long,std::ratio<60>>{10});
Godbolt Listing lst-0031-godb.cpp, https://godbolt.org/z/173nr4xxd:
//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/173nr4xxd
sleep(10min);
sleep(std::chrono::minutes{10});
sleep(std::chrono::duration<unsigned long,std::ratio<60>>{10});
GodboltId:5snr1hq9b
Book listing lst-0032-book.cpp:
// https://godbolt.org/z/5snr1hq9b
#include <chrono>
void sleep(std::chrono::seconds s) { // takes seconds as duration
/* ... */
}
/* ... */
int main() {
using namespace std::chrono; // make literals available
sleep(10min); // wait for 10 minutes, i.e., 600 seconds
sleep(10ms); // (ERR) 10 milliseconds? Cannot be represented with seconds.
}
Godbolt Listing lst-0032-godb.cpp, https://godbolt.org/z/5snr1hq9b:
//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5snr1hq9b
#include <chrono>
void sleep(std::chrono::seconds s) { // takes seconds as duration
/* ... */
}
/* ... */
int main() {
using namespace std::chrono; // make literals available
sleep(10min); // wait for 10 minutes, i.e., 600 seconds
sleep(10ms); // (ERR) 10 milliseconds? Cannot be represented with seconds.
}
GodboltId:h8vsjxsME
Book listing lst-0034-book.cpp:
// https://godbolt.org/z/h8vsjxsME
#include <cinttypes> // int64_t
namespace std { namespace chrono {
class seconds {
int64_t sec_;
public:
seconds() = default;
// … etc …
};
} }
Godbolt Listing lst-0034-godb.cpp, https://godbolt.org/z/h8vsjxsME:
//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h8vsjxsME
#include <cinttypes> // int64_t
namespace std { namespace chrono {
class seconds {
int64_t sec_;
public:
seconds() = default;
// … etc …
};
} }
Listing 28.22: With “seconds”, you can perform calculations.
Book listing lst-0039-book.cpp:
// https://godbolt.org/z/47j8h9e7v
#include <chrono>
#include <iostream>
void sleep(std::chrono::seconds dur) {
std::cout << dur.count() << "s\n";
/* ... */
}
int main() {
using namespace std::chrono;
sleep(3); // (ERR) Error: no implicit conversion from int
sleep(seconds{4}); // okay
sleep(5s); // okay
seconds x{6};
sleep(x); // okay
auto y = 10s;
y += 20s; // Incrementing with seconds
sleep(y); // now 30s
y = y - 6s; // Subtraction of seconds
sleep(y); // and now only 24s
y /= 2; // Division by a scalar
sleep(y); // 12s
sleep(y + 7); // (ERR) Error: seconds+int is not allowed
}
Godbolt Listing lst-0039-godb.cpp, https://godbolt.org/z/47j8h9e7v:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/47j8h9e7v
#include <chrono>
#include <iostream>
void sleep(std::chrono::seconds dur) {
std::cout << dur.count() << "s\n";
/* ... */
}
int main() {
using namespace std::chrono;
sleep(3); // (ERR) Error: no implicit conversion from int
sleep(seconds{4}); // okay
sleep(5s); // okay
seconds x{6};
sleep(x); // okay
auto y = 10s;
y += 20s; // Incrementing with seconds
sleep(y); // now 30s
y = y - 6s; // Subtraction of seconds
sleep(y); // and now only 24s
y /= 2; // Division by a scalar
sleep(y); // 12s
sleep(y + 7); // (ERR) Error: seconds+int is not allowed
}
Listing 28.23: You can compare “seconds”.
Book listing lst-0040-book.cpp:
// https://godbolt.org/z/8c1r5xrs5
#include <chrono>
#include <iostream>
using std::chrono::operator""s; // only make literal suffix available
constexpr auto limit = 10s;
void action(std::chrono::seconds dur) {
if(dur <= limit) { // compare
std::cout << dur.count() << "s\n";
} else {
std::cout << "too long!\n";
}
}
int main() {
action(4s); // Output: 4s
action(20s); // Output: too long!
}
Godbolt Listing lst-0040-godb.cpp, https://godbolt.org/z/8c1r5xrs5:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8c1r5xrs5
#include <chrono>
#include <iostream>
using std::chrono::operator""s; // only make literal suffix available
constexpr auto limit = 10s;
void action(std::chrono::seconds dur) {
if(dur <= limit) { // compare
std::cout << dur.count() << "s\n";
} else {
std::cout << "too long!\n";
}
}
int main() {
action(4s); // Output: 4s
action(20s); // Output: too long!
}
Listing 28.24: Automatic conversion between time units.
Book listing lst-0041-book.cpp:
// https://godbolt.org/z/qrs63vdz1
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono; // Allow suffixes
seconds mySecs = 121s; // seconds{121}
std::cout << mySecs.count() << "s\n"; // Output: 121s
milliseconds myMillis = mySecs; // automatically converted
std::cout << myMillis.count() << "ms\n"; // Output: 121000ms
nanoseconds myNanos = mySecs;
std::cout << myNanos.count() << "ns\n"; // Output: 121000000000ns
minutes myMinutesErr = mySecs; // (ERR) Error: Conversion with loss
minutes myMinutes = duration_cast<minutes>(mySecs); // explicit works
std::cout<<myMinutes.count()<<"min\n"; // Output: 2min
}
Godbolt Listing lst-0041-godb.cpp, https://godbolt.org/z/qrs63vdz1:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qrs63vdz1
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono; // Allow suffixes
seconds mySecs = 121s; // seconds{121}
std::cout << mySecs.count() << "s\n"; // Output: 121s
milliseconds myMillis = mySecs; // automatically converted
std::cout << myMillis.count() << "ms\n"; // Output: 121000ms
nanoseconds myNanos = mySecs;
std::cout << myNanos.count() << "ns\n"; // Output: 121000000000ns
minutes myMinutesErr = mySecs; // (ERR) Error: Conversion with loss
minutes myMinutes = duration_cast<minutes>(mySecs); // explicit works
std::cout<<myMinutes.count()<<"min\n"; // Output: 2min
}
Listing 28.26: You can mix units.
Book listing lst-0042-book.cpp:
// https://godbolt.org/z/vTx4cdqzq
#include <chrono>
#include <iostream>
void showDuration(std::chrono::milliseconds dur) {
std::cout << dur.count() << "ms\n";
}
int main() {
using namespace std::chrono;
auto x = 2s;
auto y = 3ms;
showDuration(x + y); // Output: 2003ms
showDuration(x - y); // Output: 1997ms
}
Godbolt Listing lst-0042-godb.cpp, https://godbolt.org/z/vTx4cdqzq:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vTx4cdqzq
#include <chrono>
#include <iostream>
void showDuration(std::chrono::milliseconds dur) {
std::cout << dur.count() << "ms\n";
}
int main() {
using namespace std::chrono;
auto x = 2s;
auto y = 3ms;
showDuration(x + y); // Output: 2003ms
showDuration(x - y); // Output: 1997ms
}
Listing 28.27: Create new time units or more efficient representations.
Book listing lst-0043-book.cpp:
// https://godbolt.org/z/xMz4s8K8K
#include <chrono>
#include <iostream>
using namespace std::chrono; using std::cout;
using seconds32 = duration<int32_t>; // other representation
using ten_day = duration<int,std::ratio<86400*10>>; // other time unit
using fseconds = duration<double>; // Floating point representation
int main() {
seconds32 s{5};
cout << milliseconds(s).count() << "ms\n";
ten_day z{1};
hours h = z; // Conversion free
cout << "1 ten_day has "<<h.count()<<" hours\n"; // …240…
fseconds fs{23.75};
cout << fs.count() << "s\n"; // Floating point output
auto printDur = [](fseconds f) { cout << f.count() << "s\n"; }; // Function
printDur(45ms + 63us); // Conversion to fseconds
// Output: 0.045063s
}
Godbolt Listing lst-0043-godb.cpp, https://godbolt.org/z/xMz4s8K8K:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/xMz4s8K8K
#include <chrono>
#include <iostream>
using namespace std::chrono; using std::cout;
using seconds32 = duration<int32_t>; // other representation
using ten_day = duration<int,std::ratio<86400*10>>; // other time unit
using fseconds = duration<double>; // Floating point representation
int main() {
seconds32 s{5};
cout << milliseconds(s).count() << "ms\n";
ten_day z{1};
hours h = z; // Conversion free
cout << "1 ten_day has "<<h.count()<<" hours\n"; // …240…
fseconds fs{23.75};
cout << fs.count() << "s\n"; // Floating point output
auto printDur = [](fseconds f) { cout << f.count() << "s\n"; }; // Function
printDur(45ms + 63us); // Conversion to fseconds
// Output: 0.045063s
}
GodboltId:zMqjqMeav
Book listing lst-0044-book.cpp:
// https://godbolt.org/z/zMqjqMeav
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
year y{2021};
std::cout << y << "\n";
month m{October};
auto result = m + months{3}; // 'months', not 'month': 3 months later
std::cout << result << "\n"; // overflowed to January
weekday wd{Thursday};
auto result = wd + days{4}; // 'days', not 'day': 4 days later
std::cout << result << "\n"; // overflowed to Monday
weekday sun1{0}; // 0 is Sunday
weekday sun2{7}; // 7 is also Sunday
std::cout << sun1 << "\t" << sun2 << "\n";
weekday_indexed wdi{wd, 4}; // unspecified 4th Thursday
std::cout << wdi << "\n"; // Output: Thu[4] — as given by chrono
// unspecified values
}
Godbolt Listing lst-0044-godb.cpp, https://godbolt.org/z/zMqjqMeav:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/zMqjqMeav
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
year y{2021};
std::cout << y << "\n";
month m{October};
auto result = m + months{3}; // 'months', not 'month': 3 months later
std::cout << result << "\n"; // overflowed to January
weekday wd{Thursday};
auto result = wd + days{4}; // 'days', not 'day': 4 days later
std::cout << result << "\n"; // overflowed to Monday
weekday sun1{0}; // 0 is Sunday
weekday sun2{7}; // 7 is also Sunday
std::cout << sun1 << "\t" << sun2 << "\n";
weekday_indexed wdi{wd, 4}; // unspecified 4th Thursday
std::cout << wdi << "\n"; // Output: Thu[4] — as given by chrono
// unspecified values
}
GodboltId:6z48xvvvM
Book listing lst-0045-book.cpp:
// https://godbolt.org/z/6z48xvvvM
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
year this_year{2021};
year last_year{2020};
year_month_day ymd{this_year, October, day{28}};
std::cout << ymd << "\n";
month_weekday mwd{November, Thursday[4]}; // in an unspecified year
std::cout << mwd << "\n"; // Output: Nov/Thu[4]
month_day_last mdlast{February}; // last day of an unspecified February
year_month_day_last leap{last_year, mdlast}; // Add year
year_month_day_last noleap{this_year, mdlast}; // Add year
std::cout << leap << "\t" << leap.day() << "\n"; // Output: 2020-02-29 29
std::cout << noleap << "\t" << noleap.day() << "\n"; // Output: 2021-02-28 28
}
Godbolt Listing lst-0045-godb.cpp, https://godbolt.org/z/6z48xvvvM:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/6z48xvvvM
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
year this_year{2021};
year last_year{2020};
year_month_day ymd{this_year, October, day{28}};
std::cout << ymd << "\n";
month_weekday mwd{November, Thursday[4]}; // in an unspecified year
std::cout << mwd << "\n"; // Output: Nov/Thu[4]
month_day_last mdlast{February}; // last day of an unspecified February
year_month_day_last leap{last_year, mdlast}; // Add year
year_month_day_last noleap{this_year, mdlast}; // Add year
std::cout << leap << "\t" << leap.day() << "\n"; // Output: 2020-02-29 29
std::cout << noleap << "\t" << noleap.day() << "\n"; // Output: 2021-02-28 28
}
GodboltId:4s69W7qd3
Book listing lst-0047-book.cpp:
// https://godbolt.org/z/4s69W7qd3
auto a_date = 2024y/11/14d;
auto b_date = 2024y/11/14;
auto c_date = 14d/11/2024;
auto d_date = November/14/2024;
Godbolt Listing lst-0047-godb.cpp, https://godbolt.org/z/4s69W7qd3:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4s69W7qd3
auto a_date = 2024y/11/14d;
auto b_date = 2024y/11/14;
auto c_date = 14d/11/2024;
auto d_date = November/14/2024;
Listing 28.28: Output of date and time with format
Book listing lst-0049-book.cpp:
// https://godbolt.org/z/Md38b9zvf
#include <chrono>
#include <iostream>
#include <format>
using namespace std::chrono;
int main() {
auto ymd = last/February/2024; // last day in February 2024: 2024-02-29
std::cout << ymd << "\n"; // the output with << is simple
std::cout << std::format("{:%Y-%m-%d}\n", ymd); // format is more flexible
std::cout << std::format("{:%e. %B %y}\n", ymd); // much more flexible!
}
Godbolt Listing lst-0049-godb.cpp, https://godbolt.org/z/Md38b9zvf:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Md38b9zvf
#include <chrono>
#include <iostream>
#include <format>
using namespace std::chrono;
int main() {
auto ymd = last/February/2024; // last day in February 2024: 2024-02-29
std::cout << ymd << "\n"; // the output with << is simple
std::cout << std::format("{:%Y-%m-%d}\n", ymd); // format is more flexible
std::cout << std::format("{:%e. %B %y}\n", ymd); // much more flexible!
}
Listing 28.29: Always the second Tuesday of a month.
Book listing lst-0050-book.cpp:
// https://godbolt.org/z/19vf9jfTM
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
for (int mo = 1; mo <= 12; ++mo) {
year_month_weekday patch_tues{mo/Tuesday[2]/2024y};
year_month_day ymd{sys_days{patch_tues}};
std::cout << ymd.month() << " " << ymd.day() << "\n";
}
}
Godbolt Listing lst-0050-godb.cpp, https://godbolt.org/z/19vf9jfTM:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/19vf9jfTM
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
for (int mo = 1; mo <= 12; ++mo) {
year_month_weekday patch_tues{mo/Tuesday[2]/2024y};
year_month_day ymd{sys_days{patch_tues}};
std::cout << ymd.month() << " " << ymd.day() << "\n";
}
}
Listing 28.30: Conversion to a time with time zone and the exceptions
Book listing lst-0052-book.cpp:
// https://godbolt.org/z/ezn568nof
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
auto spring = local_days{31d/March/2024} + 2h + 1min;
try {
auto zt = zoned_time{"Europe/Berlin", spring};
} catch (const nonexistent_local_time& e) {
std::cout << e.what() << '\n'; // Exception thrown: does not exist
}
auto autumn = local_days{27d/October/2024} + 2h + 1min;
try {
auto zt = zoned_time{"Europe/Berlin", autumn};
} catch (const ambiguous_local_time& e) {
std::cout << e.what() << '\n'; // Exception thrown: already exists
}
std::cout << zoned_time{"Europe/Berlin", autumn, choose::earliest} << '\n';
// Output: 2024-10-27 02:01:00 CEST
std::cout << zoned_time{"Europe/Berlin", autumn, choose::latest} << '\n';
// Output: 2024-10-27 02:01:00 CET
}
Godbolt Listing lst-0052-godb.cpp, https://godbolt.org/z/ezn568nof:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/ezn568nof
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
auto spring = local_days{31d/March/2024} + 2h + 1min;
try {
auto zt = zoned_time{"Europe/Berlin", spring};
} catch (const nonexistent_local_time& e) {
std::cout << e.what() << '\n'; // Exception thrown: does not exist
}
auto autumn = local_days{27d/October/2024} + 2h + 1min;
try {
auto zt = zoned_time{"Europe/Berlin", autumn};
} catch (const ambiguous_local_time& e) {
std::cout << e.what() << '\n'; // Exception thrown: already exists
}
std::cout << zoned_time{"Europe/Berlin", autumn, choose::earliest} << '\n';
// Output: 2024-10-27 02:01:00 CEST
std::cout << zoned_time{"Europe/Berlin", autumn, choose::latest} << '\n';
// Output: 2024-10-27 02:01:00 CET
}
Listing 28.31: The time zone database.
Book listing lst-0053-book.cpp:
// https://godbolt.org/z/YTKK3vT7s
#include <chrono>
#include <iostream>
#include <ranges> // views::transform, views::filter
#include <algorithm> // ranges::for_each
using namespace std; namespace c = std::chrono;
namespace v = std::views; namespace r = std::ranges;
int main() {
auto show_name = [](const string_view name) { cout << name << ' '; };
const auto& db = c::get_tzdb();
auto names = db.zones
| v::transform([](const c::time_zone& z) {return z.name();})
| v::filter([](const string_view name) {
return name.starts_with("Europe/Be");});
r::for_each(names, show_name);
cout << " <- Europe/Be*\n"; // Output: Europe/Belgrade Europe/Berlin
r::for_each(
db.links
| v::filter([](const c::time_zone_link& l){
return l.target()=="Europe/Berlin";})
| v::transform([](const c::time_zone_link& l)->string_view {
return l.name();})
, show_name);
cout << " <- Links to Europe/Berlin\n"; // Output: Arctic/Longyearbyen …
}
Godbolt Listing lst-0053-godb.cpp, https://godbolt.org/z/YTKK3vT7s:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YTKK3vT7s
#include <chrono>
#include <iostream>
#include <ranges> // views::transform, views::filter
#include <algorithm> // ranges::for_each
using namespace std; namespace c = std::chrono;
namespace v = std::views; namespace r = std::ranges;
int main() {
auto show_name = [](const string_view name) { cout << name << ' '; };
const auto& db = c::get_tzdb();
auto names = db.zones
| v::transform([](const c::time_zone& z) {return z.name();})
| v::filter([](const string_view name) {
return name.starts_with("Europe/Be");});
r::for_each(names, show_name);
cout << " <- Europe/Be*\n"; // Output: Europe/Belgrade Europe/Berlin
r::for_each(
db.links
| v::filter([](const c::time_zone_link& l){
return l.target()=="Europe/Berlin";})
| v::transform([](const c::time_zone_link& l)->string_view {
return l.name();})
, show_name);
cout << " <- Links to Europe/Berlin\n"; // Output: Arctic/Longyearbyen …
}
GodboltId:ThM8q1zEP
Book listing lst-0054-book.cpp:
// https://godbolt.org/z/ThM8q1zEP
#include <iostream>
#include <ratio>
using std::cout; using std::endl;
int main() {
using oneThird = std::ratio<1,3>;
using twoFourths = std::ratio<2,4>;
cout << oneThird::num << "/" << oneThird::den << endl; // Output: 1/3
cout << twoFourths::num << "/" << twoFourths::den << endl; // Output: 1/2
using sum = std::ratio_add<oneThird,twoFourth>; // add
cout << sum::num << "/" << sum::den; // Output: 5/6
}
Godbolt Listing lst-0054-godb.cpp, https://godbolt.org/z/ThM8q1zEP:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/ThM8q1zEP
#include <iostream>
#include <ratio>
using std::cout; using std::endl;
int main() {
using oneThird = std::ratio<1,3>;
using twoFourths = std::ratio<2,4>;
cout << oneThird::num << "/" << oneThird::den << endl; // Output: 1/3
cout << twoFourths::num << "/" << twoFourths::den << endl; // Output: 1/2
using sum = std::ratio_add<oneThird,twoFourth>; // add
cout << sum::num << "/" << sum::den; // Output: 5/6
}
GodboltId:q1znGWb85
Book listing lst-0059-book.cpp:
// https://godbolt.org/z/q1znGWb85
#include <iostream>
#include <chrono>
int main() {
using namespace std::chrono;
time_point<system_clock, seconds> t1{10000s};
time_point<system_clock, seconds> t2{50000s};
auto dur = t2 - t1;
std::cout << duration_cast<hours>(dur).count() << "h"; // Output: 11h
}
Godbolt Listing lst-0059-godb.cpp, https://godbolt.org/z/q1znGWb85:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/q1znGWb85
#include <iostream>
#include <chrono>
int main() {
using namespace std::chrono;
time_point<system_clock, seconds> t1{10000s};
time_point<system_clock, seconds> t2{50000s};
auto dur = t2 - t1;
std::cout << duration_cast<hours>(dur).count() << "h"; // Output: 11h
}
Listing 28.32: Simple timing of a function call.
Book listing lst-0063-book.cpp:
// https://godbolt.org/z/3MGbYn4d5
#include <iostream>
#include <chrono>
long fib(long n) { return n<2L ? 1L : fib(n-1L)+fib(n-2L); }
int main() {
using namespace std::chrono;
auto t0 = steady_clock::now(); // On your marks, get set …
auto res = fib(17); // … go!
auto t1 = steady_clock::now(); // Stop!
std::cout << "Result: " << res << "\n"; // Output: Result: 2584
std::cout << "Time: " << nanoseconds{t1-t0}.count() << "ns\n";
// Output: Time: 50727ns (e.g.)
}
Godbolt Listing lst-0063-godb.cpp, https://godbolt.org/z/3MGbYn4d5:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:-
// https://godbolt.org/z/3MGbYn4d5
#include <iostream>
#include <chrono>
long fib(long n) { return n<2L ? 1L : fib(n-1L)+fib(n-2L); }
int main() {
using namespace std::chrono;
auto t0 = steady_clock::now(); // On your marks, get set …
auto res = fib(17); // … go!
auto t1 = steady_clock::now(); // Stop!
std::cout << "Result: " << res << "\n"; // Output: Result: 2584
std::cout << "Time: " << nanoseconds{t1-t0}.count() << "ns\n";
// Output: Time: 50727ns (e.g.)
}
GodboltId:rz38hc1cx
Book listing lst-0064-book.cpp:
// https://godbolt.org/z/rz38hc1cx
auto res = fib(45);
// …
std::cout << "Time: " << duration_cast<seconds>(t1-t0).count() << "s\n";
// Output: Time: 7s (e.g.)
std::cout << "Time: " << duration<double>{t1-t0}.count() << "s\n";
// Output: Time: 7.35303s (e.g.)
}
Godbolt Listing lst-0064-godb.cpp, https://godbolt.org/z/rz38hc1cx:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rz38hc1cx
auto res = fib(45);
// …
std::cout << "Time: " << duration_cast<seconds>(t1-t0).count() << "s\n";
// Output: Time: 7s (e.g.)
std::cout << "Time: " << duration<double>{t1-t0}.count() << "s\n";
// Output: Time: 7.35303s (e.g.)
}
GodboltId:1xbhhTdEv
Book listing lst-0065-book.cpp:
// https://godbolt.org/z/1xbhhTdEv
#include <iostream>
#include <chrono>
int main() {
using namespace std::chrono;
auto tp = time_point_cast<seconds>(system_clock::now());
auto d = tp.time_since_epoch();
std::cout << d.count() << "s\n";
std::cout << duration<double,std::ratio<86400>>{d}.count() << "days\n";
}
Godbolt Listing lst-0065-godb.cpp, https://godbolt.org/z/1xbhhTdEv:
//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1xbhhTdEv
#include <iostream>
#include <chrono>
int main() {
using namespace std::chrono;
auto tp = time_point_cast<seconds>(system_clock::now());
auto d = tp.time_since_epoch();
std::cout << d.count() << "s\n";
std::cout << duration<double,std::ratio<86400>>{d}.count() << "days\n";
}
GodboltId:o359TThMj
Book listing lst-0066-book.cpp:
// https://godbolt.org/z/o359TThMj
#include <iostream>
#include <string>
#include <chrono>
#include <complex>
using std::cout;
int main() {
{ using namespace std;
cout << "string"s << "\n"; // string
cout << (1.2+3.4i) << "\n"; // complex
}
{ using namespace std::chrono;
cout << (35ms).count() << "ms\n"; // chrono
}
{ using namespace std::literals;
cout << (41s).count() << "ms\n"; // chrono seconds
cout << "text"s << "\n"; // string
}
{ using namespace std::chrono;
cout << (4h).count() << "h\n"; // chrono hours
}
{ using namespace std::literals::chrono_literals;
cout << (16min).count() << "min\n"; // chrono minutes
}
{ using std::literals::string_literals::operator""s;
cout << "letters"s << "\n"; // string
}
}
Godbolt Listing lst-0066-godb.cpp, https://godbolt.org/z/o359TThMj:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/o359TThMj
#include <iostream>
#include <string>
#include <chrono>
#include <complex>
using std::cout;
int main() {
{ using namespace std;
cout << "string"s << "\n"; // string
cout << (1.2+3.4i) << "\n"; // complex
}
{ using namespace std::chrono;
cout << (35ms).count() << "ms\n"; // chrono
}
{ using namespace std::literals;
cout << (41s).count() << "ms\n"; // chrono seconds
cout << "text"s << "\n"; // string
}
{ using namespace std::chrono;
cout << (4h).count() << "h\n"; // chrono hours
}
{ using namespace std::literals::chrono_literals;
cout << (16min).count() << "min\n"; // chrono minutes
}
{ using std::literals::string_literals::operator""s;
cout << "letters"s << "\n"; // string
}
}
Listing 28.34: Very simple example of how to check the success of an operation.
Book listing lst-0067-book.cpp:
// https://godbolt.org/z/1xnY8vd8Y
#include <system_error> // error_code
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
std::error_code ec;
create_dir("/some/path", ec);
if(!ec) { // Success …
} else { // Failure …
}
}
Godbolt Listing lst-0067-godb.cpp, https://godbolt.org/z/1xnY8vd8Y:
//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1xnY8vd8Y
#include <system_error> // error_code
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
std::error_code ec;
create_dir("/some/path", ec);
if(!ec) { // Success …
} else { // Failure …
}
}
Listing 28.35: Comparison of “error_code” with “error_condition”.
Book listing lst-0068-book.cpp:
// https://godbolt.org/z/TPWc5nexq
#include <system_error> // error_code, errc
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
std::error_code ec;
create_dir("/some/path", ec);
if(ec == std::errc::file_exists) { // specifically …
} else if(!ec) { // Success …
} else { // Failure …
}
}
Godbolt Listing lst-0068-godb.cpp, https://godbolt.org/z/TPWc5nexq:
//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TPWc5nexq
#include <system_error> // error_code, errc
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
std::error_code ec;
create_dir("/some/path", ec);
if(ec == std::errc::file_exists) { // specifically …
} else if(!ec) { // Success …
} else { // Failure …
}
}
Listing 28.36: Overloads of “operator==()” (abbreviated).
Book listing lst-0069-book.cpp:
bool operator==
(const error_code& lhs, const error_code& rhs) noexcept;
…(const error_code& lhs, const error_condition& rhs) noexcept;
…(const error_condition& lhs, const error_code& rhs) noexcept;
…(const error_condition& lhs, const error_condition& rhs) noexcept;
Listing 28.37: Definition of “enum class errc”.
Book listing lst-0070-book.cpp:
enum class errc {
address_family_not_supported,
address_in_use,
// ...
value_too_large,
wrong_protocol_type,
};
Listing 28.38: Specialization of “is_error_condition_enum” for “errc”.
Book listing lst-0071-book.cpp:
template <>
struct is_error_condition_enum<errc> : true_type {};
Listing 28.39: Among the overloads of “make_error_condition” is also one with “errc”.
Book listing lst-0072-book.cpp:
error_condition make_error_condition(errc c) noexcept {
return error_condition(
static_cast<int>(e),
generic_category());
}
error_condition make_error_condition(io_errc c) noexcept /*...*/
error_condition make_error_condition(future_errc c) noexcept /*...*/
Listing 28.40: Generating system-specific error codes in a portable program.
Book listing lst-0073-book.cpp:
// https://godbolt.org/z/n4v78WWod
#include <system_error>
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec) {
#if defined(_WIN32)
// Windows implementation, with Windows error codes
#elif defined(linux)
// Linux implementation, with Linux error codes
#else
// general 'generic' case
ec = std::make_error_code(std::errc::not_supported);
#endif
}
Godbolt Listing lst-0073-godb.cpp, https://godbolt.org/z/n4v78WWod:
//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n4v78WWod
#include <system_error>
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec) {
#if defined(_WIN32)
// Windows implementation, with Windows error codes
#elif defined(linux)
// Linux implementation, with Linux error codes
#else
// general 'generic' case
ec = std::make_error_code(std::errc::not_supported);
#endif
}
GodboltId:11Tdr6aG1
Book listing lst-0074-book.cpp:
// https://godbolt.org/z/11Tdr6aG1
#include <system_error>
#include <iostream>
using std::error_code; using std::system_category;
namespace mylib {
// custom error codes
enum class errc { LOAD_ERR = 1, UNLOAD_ERR = 2, OTHER_ERR = 3 };
error_code make_error_code(errc ec) {
switch(ec) {
case errc::LOAD_ERR: return error_code((int)ec, system_category());
case errc::UNLOAD_ERR: return error_code((int)ec, system_category());
case errc::OTHER_ERR: return error_code((int)ec, system_category());
}
}
error_code run(int arg) {
if(arg == 667) {
return make_error_code(errc::OTHER_ERR);
}
return error_code{}; // all good.
}
}
int main() {
std::error_code ec = mylib::run(667);
if(!ec) {
std::cout << "Great, it works!\n";
} else if (ec == mylib::make_error_code(mylib::errc::OTHER_ERR)) {
std::cout << "Another error\n";
} else {
std::cout << "Nothing happening here\n" << ec;
}
}
Godbolt Listing lst-0074-godb.cpp, https://godbolt.org/z/11Tdr6aG1:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23 -Wno-return-type; libs:-
// https://godbolt.org/z/11Tdr6aG1
#include <system_error>
#include <iostream>
using std::error_code; using std::system_category;
namespace mylib {
// custom error codes
enum class errc { LOAD_ERR = 1, UNLOAD_ERR = 2, OTHER_ERR = 3 };
error_code make_error_code(errc ec) {
switch(ec) {
case errc::LOAD_ERR: return error_code((int)ec, system_category());
case errc::UNLOAD_ERR: return error_code((int)ec, system_category());
case errc::OTHER_ERR: return error_code((int)ec, system_category());
}
}
error_code run(int arg) {
if(arg == 667) {
return make_error_code(errc::OTHER_ERR);
}
return error_code{}; // all good.
}
}
int main() {
std::error_code ec = mylib::run(667);
if(!ec) {
std::cout << "Great, it works!\n";
} else if (ec == mylib::make_error_code(mylib::errc::OTHER_ERR)) {
std::cout << "Another error\n";
} else {
std::cout << "Nothing happening here\n" << ec;
}
}
GodboltId:a8zP84j1x
Book listing lst-0076-book.cpp:
// https://godbolt.org/z/a8zP84j1x
#include <thread>
#include <iostream>
#include <system_error>
int main() {
try {
std::thread().detach(); // this will fail
} catch(std::system_error& e) {
std::cout
<< "system_error with code:" << e.code()
<< " message:" << e.what()
<< '\n';
}
}
Godbolt Listing lst-0076-godb.cpp, https://godbolt.org/z/a8zP84j1x:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a8zP84j1x
#include <thread>
#include <iostream>
#include <system_error>
int main() {
try {
std::thread().detach(); // this will fail
} catch(std::system_error& e) {
std::cout
<< "system_error with code:" << e.code()
<< " message:" << e.what()
<< '\n';
}
}
GodboltId:cjh93oPcr
Book listing lst-0077-book.cpp:
// https://godbolt.org/z/cjh93oPcr
#include <iostream>
#include <system_error> // std::make_error_condition, std::ios_errc
int main () {
// switch to exceptions:
std::cin.exceptions (std::ios::failbit|std::ios::badbit);
try {
std::cin.rdbuf(nullptr); // triggers an exception
} catch (std::ios::failure& e) { // derived from system_error
std::cerr << "Error: ";
if (e.code() == std::make_error_condition(std::io_errc::stream)) {
std::cerr << "stream\n";
} else {
std::cerr << "other\n";
}
}
}
Godbolt Listing lst-0077-godb.cpp, https://godbolt.org/z/cjh93oPcr:
//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cjh93oPcr
#include <iostream>
#include <system_error> // std::make_error_condition, std::ios_errc
int main () {
// switch to exceptions:
std::cin.exceptions (std::ios::failbit|std::ios::badbit);
try {
std::cin.rdbuf(nullptr); // triggers an exception
} catch (std::ios::failure& e) { // derived from system_error
std::cerr << "Error: ";
if (e.code() == std::make_error_condition(std::io_errc::stream)) {
std::cerr << "stream\n";
} else {
std::cerr << "other\n";
}
}
}
Listing 28.41: Use “typeindex” for reliable type information.
Book listing lst-0078-book.cpp:
// https://godbolt.org/z/d1G9ez4KW
#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <string>
struct Base {
virtual ~Base() {}
};
struct Derived_One : public Base {};
struct Derived_Two : public Base {};
int main() {
using std::string; using std::cout; using std::type_index;
std::map<std::type_index, string> names {
{ type_index(typeid(int)), "int" },
{ type_index(typeid(double)), "double" },
{ type_index(typeid(Base)), "Base" },
{ type_index(typeid(Derived_One)), "Derived_One" },
{ type_index(typeid(Derived_Two)), "Derived_Two" },
{ type_index(typeid(string)), "string" },
{ type_index(typeid(string::const_iterator)), "string" },
};
names[type_index(typeid(names))] = "names-map";
int integer;
double floating;
Base base{};
Base *one = new Derived_One{};
Base *two = new Derived_Two{};
// typeid.name() is implementation- and runtime-dependent:
cout << typeid(integer).name() << '\n'; // On my system: i
cout << typeid(floating).name() << '\n'; // On my system: d
cout << typeid(base).name() << '\n'; // On my system: 4Base
cout << typeid(*one).name() << '\n'; // On my system: 11Derived_One
cout << typeid(*two).name() << '\n'; // On my system: 11Derived_Two
cout << typeid(string).name() << '\n'; // For me: Ss
cout << typeid(string{"World"}.begin()).name() << '\n';
// For me: N9__gnu_cxx17__normal_iteratorIPcSsEE
cout << typeid(names).name() << '\n';
// For me: St3mapISt10type_indexSsSt4lessIS0_ESaISt4pairIKS0_SsEEE
cout << typeid(666/0).name() << '\n'; // Expression not executed! For me: i
// type_index makes type_infos comparable:
cout << names[type_index(typeid(integer))] << '\n'; // Output: int
cout << names[type_index(typeid(floating))] << '\n'; // Output: double
cout << names[type_index(typeid(base))] << '\n'; // Output: Base
cout << names[type_index(typeid(*one))] << '\n'; // Output: Derived_One
cout << names[type_index(typeid(*two))] << '\n'; // Output: Derived_Two
cout << names[type_index(typeid(string))] << '\n'; // Output: string
cout << names[type_index(typeid(names))] << '\n'; // Output: names-map
}
Godbolt Listing lst-0078-godb.cpp, https://godbolt.org/z/d1G9ez4KW:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23 -Wno-return-type; libs:-
// https://godbolt.org/z/d1G9ez4KW
#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <string>
struct Base {
virtual ~Base() {}
};
struct Derived_One : public Base {};
struct Derived_Two : public Base {};
int main() {
using std::string; using std::cout; using std::type_index;
std::map<std::type_index, string> names {
{ type_index(typeid(int)), "int" },
{ type_index(typeid(double)), "double" },
{ type_index(typeid(Base)), "Base" },
{ type_index(typeid(Derived_One)), "Derived_One" },
{ type_index(typeid(Derived_Two)), "Derived_Two" },
{ type_index(typeid(string)), "string" },
{ type_index(typeid(string::const_iterator)), "string" },
};
names[type_index(typeid(names))] = "names-map";
int integer;
double floating;
Base base{};
Base *one = new Derived_One{};
Base *two = new Derived_Two{};
// typeid.name() is implementation- and runtime-dependent:
cout << typeid(integer).name() << '\n'; // On my system: i
cout << typeid(floating).name() << '\n'; // On my system: d
cout << typeid(base).name() << '\n'; // On my system: 4Base
cout << typeid(*one).name() << '\n'; // On my system: 11Derived_One
cout << typeid(*two).name() << '\n'; // On my system: 11Derived_Two
cout << typeid(string).name() << '\n'; // For me: Ss
cout << typeid(string{"World"}.begin()).name() << '\n';
// For me: N9__gnu_cxx17__normal_iteratorIPcSsEE
cout << typeid(names).name() << '\n';
// For me: St3mapISt10type_indexSsSt4lessIS0_ESaISt4pairIKS0_SsEEE
cout << typeid(666/0).name() << '\n'; // Expression not executed! For me: i
// type_index makes type_infos comparable:
cout << names[type_index(typeid(integer))] << '\n'; // Output: int
cout << names[type_index(typeid(floating))] << '\n'; // Output: double
cout << names[type_index(typeid(base))] << '\n'; // Output: Base
cout << names[type_index(typeid(*one))] << '\n'; // Output: Derived_One
cout << names[type_index(typeid(*two))] << '\n'; // Output: Derived_Two
cout << names[type_index(typeid(string))] << '\n'; // Output: string
cout << names[type_index(typeid(names))] << '\n'; // Output: names-map
}
Listing 28.42: Boost’s “demangled_name” is extremely useful for outputting type names.
Book listing lst-0079-book.cpp:
// https://godbolt.org/z/n54566cqT
#include <iostream>
#include <typeinfo>
#include <string>
#include <map>
#include <boost/core/typeinfo.hpp>
int main() {
using std::string; using std::cout;
std::map<int, string> names;
int i;
double f;
// demangled_name
using boost::core::demangled_name;
cout<<demangled_name(BOOST_CORE_TYPEID(i))<<'\n'; // Output: int
cout<<demangled_name(BOOST_CORE_TYPEID(f))<<'\n'; // Output: double
cout<<demangled_name(BOOST_CORE_TYPEID(string))<<'\n'; // Output: std::string
cout<<demangled_name(BOOST_CORE_TYPEID(string{}.begin()))<<'\n';
// Output: __gnu_cxx::__normal_iterator<char*, std::string>
cout<<demangled_name(BOOST_CORE_TYPEID(namen))<<'\n';
// Output: std::map<int, std::string, std::less<int>,
// std::allocator<std::pair<int const, std::string> > >
cout<<demangled_name(BOOST_CORE_TYPEID(666/0))<<'\n'; // Output: int
}
Godbolt Listing lst-0079-godb.cpp, https://godbolt.org/z/n54566cqT:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n54566cqT
#include <iostream>
#include <typeinfo>
#include <string>
#include <map>
#include <boost/core/typeinfo.hpp>
int main() {
using std::string; using std::cout;
std::map<int, string> names;
int i;
double f;
// demangled_name
using boost::core::demangled_name;
cout<<demangled_name(BOOST_CORE_TYPEID(i))<<'\n'; // Output: int
cout<<demangled_name(BOOST_CORE_TYPEID(f))<<'\n'; // Output: double
cout<<demangled_name(BOOST_CORE_TYPEID(string))<<'\n'; // Output: std::string
cout<<demangled_name(BOOST_CORE_TYPEID(string{}.begin()))<<'\n';
// Output: __gnu_cxx::__normal_iterator<char*, std::string>
cout<<demangled_name(BOOST_CORE_TYPEID(namen))<<'\n';
// Output: std::map<int, std::string, std::less<int>,
// std::allocator<std::pair<int const, std::string> > >
cout<<demangled_name(BOOST_CORE_TYPEID(666/0))<<'\n'; // Output: int
}
GodboltId:Y3GsPd97d
Book listing lst-0081-book.cpp:
// https://godbolt.org/z/Y3GsPd97d
#include <set>
#include <string>
struct Dragon {
std::string name_;
};
namespace std {
template<> struct less<Dragon> { // Template specialization
bool operator()(const Dragon &lhs, const Dragon &rhs) const {
return lhs.name_ < rhs.name_;
} }; }
int main() {
std::set<Dragon> dragons {
Dragon{"Smaug"}, Dragon{"Glaurung"},
Dragon{"Ancalagon"},Dragon{"Scatha"}};
}
Godbolt Listing lst-0081-godb.cpp, https://godbolt.org/z/Y3GsPd97d:
//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y3GsPd97d
#include <set>
#include <string>
struct Dragon {
std::string name_;
};
namespace std {
template<> struct less<Dragon> { // Template specialization
bool operator()(const Dragon &lhs, const Dragon &rhs) const {
return lhs.name_ < rhs.name_;
} }; }
int main() {
std::set<Dragon> dragons {
Dragon{"Smaug"}, Dragon{"Glaurung"},
Dragon{"Ancalagon"},Dragon{"Scatha"}};
}
Listing 28.43: This calculator maps keys to functors.
Book listing lst-0082-book.cpp:
// https://godbolt.org/z/jxvhded75
#include <string>
#include <vector>
#include <iostream>
#include <map>
#include <functional>
std::map<char,std::function<int(int,int)>> binOps { // binary operators
{'+', std::plus<int>{} },
{'-', std::minus<int>{} },
{'*', std::multiplies<int>{} },
{'/', std::divides<int>{} },
{'%', std::modulus<int>{} },
};
std::map<char,std::function<int(int)>> unOps { }; // unary operators
auto val = [](auto n) { return [n](){ return n; };}; // returns a lambda
std::map<char,std::function<int()>> zeroOps { // nullary operators
{'0', val(0)}, {'1', val(1)}, {'2', val(2)}, {'3', val(3)}, {'4', val(4)},
{'5', val(5)}, {'6', val(6)}, {'7', val(7)}, {'8', val(8)}, {'9', val(9)},
};
std::map<char,std::function<void(std::vector<int>&)>> stackOps {
{ ' ', [](auto &stack) { } }, // no operation
{ 'c', [](auto &stack) { stack.clear(); } }, // Clear the entire stack
{ ':', [](auto &stack) { // swap the top two elements
auto top = stack.back(); stack.pop_back();
auto second = stack.back(); stack.pop_back();
stack.push_back(top);
stack.push_back(second);
} },
{ '=', [](auto &stack) { // print the entire stack
for(int elem : stack) { std::cout << elem; }
std::cout << "\n";
} },
};
void calculator(std::string input) {
std::vector<int> stack {};
for(char c : input) {
int top, second;
if(auto it = unOps.find(c); it != unOps.end()) {
// if unary operator …
auto func = it->second;
top = stack.back(); stack.pop_back(); // … get top element
stack.push_back(func(top)); // … apply func, push result onto stack
} else if(auto it = binOps.find(c); it != binOps.end()) {
// if binary operator …
auto func = it->second;
top = stack.back(); stack.pop_back(); // … get the top 2 elements
second = stack.back(); stack.pop_back();
stack.push_back(func(second, top));// … apply func, push result onto stack
} else if(auto it = zeroOps.find(c); it !=zeroOps.end()) {
// if nullary operator …
auto func = it->second;
stack.push_back(func()); // ... result of func on stack
} else if(auto it = stackOps.find(c); it != stackOps.end()) {
// if stack operator
auto func = it->second;
func(stack); // ... apply func to stack
} else {
std::cout << "\n'" << c << "' I don't understand.\n";
}
} /* for c */
}
int main(int argc, const char* argv[]) {
if(argc > 1) {
calculator(argv[1]);
} else {
// 3+4*5+6 with multiplication before addition results in 29
calculator("345*+6+=");
}
calculator("93-="); // 9 - 3 = Output: 6
calculator("82/="); // 8 / 2 = Output: 4
calculator("92%="); // 9 % 2 = Output: 1
}
Godbolt Listing lst-0082-godb.cpp, https://godbolt.org/z/jxvhded75:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:boost@184
// https://godbolt.org/z/jxvhded75
#include <string>
#include <vector>
#include <iostream>
#include <map>
#include <functional>
std::map<char,std::function<int(int,int)>> binOps { // binary operators
{'+', std::plus<int>{} },
{'-', std::minus<int>{} },
{'*', std::multiplies<int>{} },
{'/', std::divides<int>{} },
{'%', std::modulus<int>{} },
};
std::map<char,std::function<int(int)>> unOps { }; // unary operators
auto val = [](auto n) { return [n](){ return n; };}; // returns a lambda
std::map<char,std::function<int()>> zeroOps { // nullary operators
{'0', val(0)}, {'1', val(1)}, {'2', val(2)}, {'3', val(3)}, {'4', val(4)},
{'5', val(5)}, {'6', val(6)}, {'7', val(7)}, {'8', val(8)}, {'9', val(9)},
};
std::map<char,std::function<void(std::vector<int>&)>> stackOps {
{ ' ', [](auto &stack) { } }, // no operation
{ 'c', [](auto &stack) { stack.clear(); } }, // Clear the entire stack
{ ':', [](auto &stack) { // swap the top two elements
auto top = stack.back(); stack.pop_back();
auto second = stack.back(); stack.pop_back();
stack.push_back(top);
stack.push_back(second);
} },
{ '=', [](auto &stack) { // print the entire stack
for(int elem : stack) { std::cout << elem; }
std::cout << "\n";
} },
};
void calculator(std::string input) {
std::vector<int> stack {};
for(char c : input) {
int top, second;
if(auto it = unOps.find(c); it != unOps.end()) {
// if unary operator …
auto func = it->second;
top = stack.back(); stack.pop_back(); // … get top element
stack.push_back(func(top)); // … apply func, push result onto stack
} else if(auto it = binOps.find(c); it != binOps.end()) {
// if binary operator …
auto func = it->second;
top = stack.back(); stack.pop_back(); // … get the top 2 elements
second = stack.back(); stack.pop_back();
stack.push_back(func(second, top));// … apply func, push result onto stack
} else if(auto it = zeroOps.find(c); it !=zeroOps.end()) {
// if nullary operator …
auto func = it->second;
stack.push_back(func()); // ... result of func on stack
} else if(auto it = stackOps.find(c); it != stackOps.end()) {
// if stack operator
auto func = it->second;
func(stack); // ... apply func to stack
} else {
std::cout << "\n'" << c << "' I don't understand.\n";
}
} /* for c */
}
int main(int argc, const char* argv[]) {
if(argc > 1) {
calculator(argv[1]);
} else {
// 3+4*5+6 with multiplication before addition results in 29
calculator("345*+6+=");
}
calculator("93-="); // 9 - 3 = Output: 6
calculator("82/="); // 8 / 2 = Output: 4
calculator("92%="); // 9 % 2 = Output: 1
}
GodboltId:e6xT638ch
Book listing lst-0083-book.cpp:
// https://godbolt.org/z/e6xT638ch
#include <functional> // subtract, minus, bind
#include <iostream>
using std::cout;
int subtract(int a, int b) { return a - b; }
int main() {
using namespace std::placeholders;
cout << subtract(9, 3) << '\n' ; // Output: 6
auto minus3 = std::bind(subtract, _1, 3);
cout << minus3(9) << '\n'; // Output: 6
auto from9 = std::bind(subtract, 9, _1);
cout << from9(3) << '\n'; // Output: 6
auto againMinus3 = std::bind(std::minus<int>{}, _1, 3);
cout << againMinus3(9) << '\n'; // Output: 6
}
Godbolt Listing lst-0083-godb.cpp, https://godbolt.org/z/e6xT638ch:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/e6xT638ch
#include <functional> // subtract, minus, bind
#include <iostream>
using std::cout;
int subtract(int a, int b) { return a - b; }
int main() {
using namespace std::placeholders;
cout << subtract(9, 3) << '\n' ; // Output: 6
auto minus3 = std::bind(subtract, _1, 3);
cout << minus3(9) << '\n'; // Output: 6
auto from9 = std::bind(subtract, 9, _1);
cout << from9(3) << '\n'; // Output: 6
auto againMinus3 = std::bind(std::minus<int>{}, _1, 3);
cout << againMinus3(9) << '\n'; // Output: 6
}
Listing 28.44: With “bind”, you can also set all parameters of a function.
Book listing lst-0084-book.cpp:
// https://godbolt.org/z/j7sa9rexh
#include <random>
#include <vector>
#include <iostream>
#include <functional>
void rollDice() {
std::default_random_engine engine{};
std::vector<size_t> counts{0,0,0,0,0,0};
std::uniform_int_distribution<int> d6{0, 5}; // uniformly distributed integers
auto d = std::bind(d6, engine); // d() = d6(engine)
for(auto i=1200*1000; i>0; --i) ++counts[d()];
for(auto c : counts) std::cout<<" "<<c;
std::cout << '\n';
}
int main() {
rollDice();
}
Godbolt Listing lst-0084-godb.cpp, https://godbolt.org/z/j7sa9rexh:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:boost@184
// https://godbolt.org/z/j7sa9rexh
#include <random>
#include <vector>
#include <iostream>
#include <functional>
void rollDice() {
std::default_random_engine engine{};
std::vector<size_t> counts{0,0,0,0,0,0};
std::uniform_int_distribution<int> d6{0, 5}; // uniformly distributed integers
auto d = std::bind(d6, engine); // d() = d6(engine)
for(auto i=1200*1000; i>0; --i) ++counts[d()];
for(auto c : counts) std::cout<<" "<<c;
std::cout << '\n';
}
int main() {
rollDice();
}
Listing 28.45: This is how you turn class members into free functions.
Book listing lst-0087-book.cpp:
// https://godbolt.org/z/GMjcjrvaT
#include <functional>
#include <iostream>
struct Numbers {
int theNumber() {
return 42;
}
int more(int n) {
return n + data;
}
int data = 7;
};
int main() {
auto func = std::mem_fn(&Numbers::theNumber);
auto func2 = std::mem_fn(&Numbers::more);
auto access = std::mem_fn(&Numbers::data);
Numbers numbers;
std::cout << func(numbers) << '\n'; // Output: 42
std::cout << func2(numbers, 66) << '\n'; // Output: 73
std::cout << access(numbers) << '\n'; // Output: 7
}
Godbolt Listing lst-0087-godb.cpp, https://godbolt.org/z/GMjcjrvaT:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:boost@184
// https://godbolt.org/z/GMjcjrvaT
#include <functional>
#include <iostream>
struct Numbers {
int theNumber() {
return 42;
}
int more(int n) {
return n + data;
}
int data = 7;
};
int main() {
auto func = std::mem_fn(&Numbers::theNumber);
auto func2 = std::mem_fn(&Numbers::more);
auto access = std::mem_fn(&Numbers::data);
Numbers numbers;
std::cout << func(numbers) << '\n'; // Output: 42
std::cout << func2(numbers, 66) << '\n'; // Output: 73
std::cout << access(numbers) << '\n'; // Output: 7
}
Listing 28.46: Basic functionalities of “variant”.
Book listing lst-0088-book.cpp:
// https://godbolt.org/z/baY7Tz91f
#include <variant>
using std::get;
int main() {
std::variant<int, float> v{};
v = 12; // State changes to int
auto i = get<int>(v); // retrieves the int
std::cout << i << '\n'; // Output: 12
v = 3.456f; // State changes to float
std::cout << get<float>(v) << '\n'; // Output: 3.456
get<double>(v); // (ERR) Error
get<3>(v); // (ERR) Error
std::variant<int, float> w{};
w = get<float>(v); // Access by type
w = get<1>(v); // Access is also possible via index
w = v; // entire assignment is also possible
try {
get<int>(w); // triggers exception
} catch (std::bad_variant_access&) { /* ... */ }
}
Godbolt Listing lst-0088-godb.cpp, https://godbolt.org/z/baY7Tz91f:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:boost@184
// https://godbolt.org/z/baY7Tz91f
#include <variant>
using std::get;
int main() {
std::variant<int, float> v{};
v = 12; // State changes to int
auto i = get<int>(v); // retrieves the int
std::cout << i << '\n'; // Output: 12
v = 3.456f; // State changes to float
std::cout << get<float>(v) << '\n'; // Output: 3.456
get<double>(v); // (ERR) Error
get<3>(v); // (ERR) Error
std::variant<int, float> w{};
w = get<float>(v); // Access by type
w = get<1>(v); // Access is also possible via index
w = v; // entire assignment is also possible
try {
get<int>(w); // triggers exception
} catch (std::bad_variant_access&) { /* ... */ }
}
Listing 28.47: Inspecting a “variant” using a visitor.
Book listing lst-0089-book.cpp:
// https://godbolt.org/z/G4z8Y5E6P
#include <variant>
#include <iostream>
using std::cout;
struct TypeGreeting {
void operator()(int) const { cout << "Hello int"; }
void operator()(float) const { cout << "Hello float"; }
};
int main() {
std::variant<int, float> var{};
var = 12; // State int
std::visit([](auto a) { cout << a; }, var); // generic lambda
cout << std::endl;
var = 3.456f; // State float
std::visit(TypeGreeting{}, var); // Functor with overloads
cout << std::endl;
}
Godbolt Listing lst-0089-godb.cpp, https://godbolt.org/z/G4z8Y5E6P:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:boost@184
// https://godbolt.org/z/G4z8Y5E6P
#include <variant>
#include <iostream>
using std::cout;
struct TypeGreeting {
void operator()(int) const { cout << "Hello int"; }
void operator()(float) const { cout << "Hello float"; }
};
int main() {
std::variant<int, float> var{};
var = 12; // State int
std::visit([](auto a) { cout << a; }, var); // generic lambda
cout << std::endl;
var = 3.456f; // State float
std::visit(TypeGreeting{}, var); // Functor with overloads
cout << std::endl;
}
GodboltId:1eco9Wcr3
Book listing lst-0090-book.cpp:
// https://godbolt.org/z/1eco9Wcr3
#include <any>
#include <iostream>
#include <vector>
#include <string>
int main() {
std::any a = 5;
std::cout << std::any_cast<int>(a) << '\n';
a = 3.456;
std::cout << std::any_cast<double>(a) << '\n';
using namespace std::literals;
std::vector<std::any> data { 4, 8.976, "Geronimo"s };
std::cout << std::any_cast<double>( data[1] ) << '\n';
std::cout << data[1].type().name() << '\n';
}
Godbolt Listing lst-0090-godb.cpp, https://godbolt.org/z/1eco9Wcr3:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1eco9Wcr3
#include <any>
#include <iostream>
#include <vector>
#include <string>
int main() {
std::any a = 5;
std::cout << std::any_cast<int>(a) << '\n';
a = 3.456;
std::cout << std::any_cast<double>(a) << '\n';
using namespace std::literals;
std::vector<std::any> data { 4, 8.976, "Geronimo"s };
std::cout << std::any_cast<double>( data[1] ) << '\n';
std::cout << data[1].type().name() << '\n';
}
GodboltId:115nE7xsc
Book listing lst-0093-book.cpp:
// https://godbolt.org/z/115nE7xsc
#include <charconv>
#include <vector>
#include <iostream>
#include <string>
std::vector<size_t> num_to_vec(const std::string& nums) {
std::vector<size_t> result {};
// without trailing spaces
const auto end = nums.data() + nums.find_last_not_of( ' ' ) + 1;
const char* st = nullptr; // loop pointer
auto last = nums.data(); // last untranslated character
size_t n; // converted number
do {
for(st = last; (st<end)&&(*st==' ' ); ++st); // skip ' '
if (last = std::from_chars(st, end, n).ptr; last != st)
result.push_back(n); // store number
} while (last != st);
return result;
}
void errorDemo(const char* buf, size_t sz) {
int n;
auto [p, ec] = std::from_chars(buf, buf+sz, n);
if (ec != std::errc{}) {
const auto error = std::make_error_code(ec);
std::cout << error.message() << '\n';
}
}
int main() {
auto result = num_to_vec("12 33 43");
for(auto r : result) std::cout << r << " ";
std::cout << '\n';
// Output: 12 33 43
errorDemo("XYZ", 4);
// Output: Invalid argument
errorDemo("123123123123123", 16);
// Output: Numerical result out of range
}
Godbolt Listing lst-0093-godb.cpp, https://godbolt.org/z/115nE7xsc:
//#(compile) c++; compiler:g141; options:-O1 -std=c++23; libs:boost@184
// https://godbolt.org/z/115nE7xsc
#include <charconv>
#include <vector>
#include <iostream>
#include <string>
std::vector<size_t> num_to_vec(const std::string& nums) {
std::vector<size_t> result {};
// without trailing spaces
const auto end = nums.data() + nums.find_last_not_of( ' ' ) + 1;
const char* st = nullptr; // loop pointer
auto last = nums.data(); // last untranslated character
size_t n; // converted number
do {
for(st = last; (st<end)&&(*st==' ' ); ++st); // skip ' '
if (last = std::from_chars(st, end, n).ptr; last != st)
result.push_back(n); // store number
} while (last != st);
return result;
}
void errorDemo(const char* buf, size_t sz) {
int n;
auto [p, ec] = std::from_chars(buf, buf+sz, n);
if (ec != std::errc{}) {
const auto error = std::make_error_code(ec);
std::cout << error.message() << '\n';
}
}
int main() {
auto result = num_to_vec("12 33 43");
for(auto r : result) std::cout << r << " ";
std::cout << '\n';
// Output: 12 33 43
errorDemo("XYZ", 4);
// Output: Invalid argument
errorDemo("123123123123123", 16);
// Output: Numerical result out of range
}
GodboltId:dcqenEd31
Book listing lst-0095-book.cpp:
// https://godbolt.org/z/dcqenEd31
#include <iostream>
#include <charconv>
#include <string_view>
#include <array>
int main() {
std::array<char, 10> str {};
if(auto [p, ec] = std::to_chars(str.data(), str.data() + str.size(), 42);
ec == std::errc{} )
std::cout << std::string_view(str.data(), p - str.data()) << "\n";
}
Godbolt Listing lst-0095-godb.cpp, https://godbolt.org/z/dcqenEd31:
//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dcqenEd31
#include <iostream>
#include <charconv>
#include <string_view>
#include <array>
int main() {
std::array<char, 10> str {};
if(auto [p, ec] = std::to_chars(str.data(), str.data() + str.size(), 42);
ec == std::errc{} )
std::cout << std::string_view(str.data(), p - str.data()) << "\n";
}