C++ Examples
Asserts (Static)
For type support and asserts see the CPP Reference entry which has an exhaustive list.
template <typename T>
T DoSomething(T value) {
static_assert(std::is_same<decltype(value), bool>::value, "value must be bool");
// ...
}
template <typename T>
T DoSomething(T value) {
static_assert(std::is_floating_point<T>::value,
"value must be an floating type.");
// ...
}
template <typename T>
T DoSomething(T value) {
static_assert(std::numeric_limits<T>::is_integer,
"value must be an integer type.");
// ...
}
int DoSomething(int even, int odd) {
static_assert(even % 2 == 0 "even value must be an even number.");
static_assert(odd % 2 != 0 "odd value must be an odd number.");
// ...
}
template <typename T>
std::vector<std::byte> ToBytes(const T& object) {
static_assert(
std::is_fundamental<T>::value || std::is_same<T, std::string>::value,
"object must be a fundamental or string type.");
// ...
}
Fibers
Trivial usage.
#include "boost/fiber/fiber.hpp"
// Lambda to Fiber is always std::function<void()>.
auto fiber = std::make_unique<boost::fibers::fiber>([]() { DoSomething(); });
DoSomethingElse();
fiber->join();
Using a channel to communicate data.
#include "thread/fiber/fiber.h"
#include "boost/fiber/buffered_channel.hpp"
std::string CreateText() { /* ... */ }
boost::fibers::buffered_channel<std::string> channel(0);
// Capture channel by reference in the lambda below.
auto fiber = std::make_unique<boost::fibers::fiber>([&channel]() {
channel.push(CreateText());
});
// Don't join until channel is read or it will hang.
std::string created_text;
channel->pop(&created_text);
channel->close();
fiber->join();
File
Write
#include <fstream>
#include <iostream>
#include <string_view>
std::string_view file_path = "/dir/file_path.txt";
std::string_view contents = "stuff blah blah";
std::ofstream my_file;
my_file.open(file_path, ios::out | ios::in);
my_file << contents << std::endl;
my_file.close();
Read
#include <fstream>
#include <iostream>
#include <string_view>
std::string_view file_path = "/dir/file.txt";
std::string contents;
std::ifstream my_file;
my_file.open(file_path);
my_file >> contents;
Join Paths
#include <iostream>
#include <filesystem>
std::filesystem::path file_path = "/dir";
file_path /= "*.stuff"; // Inserts separator.
List Directory
#include <string>
#include <iostream>
#include <filesystem>
#include <string_view>
namespace fs = std::filesystem;
std::string_view path = "/dir";
for (const fs::directory_entry& entry : fs::directory_iterator(path)) {
// ...
}
// or recursively
for (const fs::directory_entry& entry : fs::recursive_directory_iterator(path)) {
// ...
}
Create & Remove Directory
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <filesystem>
namespace fs = std::filesystem;
const bool created = fs::create_directories("/dir1/dir2/dir3"); // Create recursively.
const bool created = fs::create_directory("/dir1/dir2", "/dir/qux"); // Create multiple non-recursively.
const bool removed = fs::remove_all("/dir"); // Remove all directories and sub directories.
Copy
#include <filesystem>
std::filesystem::copy("/file1.txt", "/file2.txt");
std::filesystem::copy("/dir1", "/dir2");
std::filesystem::copy("/dir1", "/dir2", std::filesystem::copy_options::recursive);
Permissions
See C++ reference of std::filesystem::perms for an exhaustive list of constants.
#include <fstream>
#include <bitset>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
fs::permissions("file.txt", fs::perms::owner_all); // rwx------
fs::permissions("file.txt", fs::perms::owner_all | fs::perms::group_all); // rwxrwx---
fs::permissions("file.txt", fs::perms::others_write); // -------w-
Path Parts
#include <filesystem>
const auto path = std::filesystem::path("/dir/file.txt");
path.filename(); // file.txt
path.stem(); // file
path.extension(); // txt
path.parent_path(); // /dir
Hashed
Map
#include <map>
std::map<std::string, int> text_to_int;
text_to_int.insert(std::make_pair("foo", 1));
// or ...
text_to_int.insert({"foo", 1});
// or ...
text_to_int["foo"] = 1;
#include <map>
#include <string_view>
std::map<std::string, MyObject> text_to_int;
// ... insert stuff
for (auto it = text_to_int.begin(); it != text_to_int.end(); ++it) {
std::string_view t = it->first;
const int x = it->second;
// ...
}
#include <map>
#include <string_view>
std::map<std::string, MyObject> text_to_int;
// ... insert stuff
auto it = text_to_int.find("foo");
if (it == text_to_int.end()) {
// not found
} else {
std::string_view t = it->first;
const int x = it->second;
}
Set
#include <set>
std::set<std::string> texts;
auto pair = texts.insert("foo");
auto it = pair.first; // iterator at inserted or already inserted value
bool inserted = it.second;
#include <set>
std::set<std::string> texts;
auto it = texts.find("foo");
bool found = it != texts.end();
const std::string value = *it; // "foo"
#include <set>
std::set<std::string> texts;
texts.insert({"bar", "baz"});
Iterators
Copy
#include <algorithm>
#include <iterator>
#include <vector>
std::vector<int> source{1, 2, 3, 4};
std::vector<int> target;
std::copy(source.begin(), source.end(), target.begin());
// target = {1, 2, 3, 4}
#include <algorithm>
#include <iterator>
#include <vector>
std::vector<int> source{1, 2, 3, 4};
std::vector<int> target;
std::copy(source.begin() + 1, source.end() - 1, target.begin());
// target = {2, 3}
#include <algorithm>
#include <iterator>
#include <vector>
std::vector<int> source{1, 2, 3, 4};
std::vector<int> target;
std::copy_if(source.begin(), source.end(), target.begin(),
[](int x) { return x % 2 == 0 });
// target = {2, 4}
Filter
#include <ranges>
#include <vector>
std::vector<int> source{1, 2, 3, 4, 5};
std::vector<int> target;
auto is_even = [](int x) { return 0 == x % 2; };
auto square = [](int x) { return x * i; };
for (int element : elements | std::views::filter(is_even) |
std::views::transform(square)) {
target.push_back(element);
}
// target = { 4, 16 }
Find
#include <algorithm>
#include <vector>
#include <iterator>
std::vector<int> elements{1, 2, 3, 4};
auto it = std::find(elements.begin(), elements.end(), 3);
// *it = 3
#include <algorithm>
#include <vector>
#include <iterator>
std::vector<int> elements{1, 2, 3, 4};
auto it = std::find_if(elements.begin(), elements.end(),
[](int x) { return x == 3; });
// *it = 3
Loop
#include <vector>
#include <iterator>
std::vector<int> source{1, 2, 3, 4};
std::vector<int> target;
for (std::vector<int>::iterator it = source.begin(); it < source.end(); ++it) {
target.push_back(*it);
}
// target = {1, 2, 3, 4}
#include <vector>
#include <iterator>
std::vector<int> source{1, 2, 3, 4};
std::vector<int> target;
for (auto it = source.begin(); it < source.end() - 1; ++it) {
target.push_back(*it);
}
// target = {1, 2, 3}
#include <vector>
#include <iterator>
std::vector<int> source{1, 2, 3, 4, 5};
std::vector<int> target;
for (auto it = source.begin(); it < source.end(); ++it) {
target.push_back(*it++);
}
// target = {1, 3, 5}
#include <vector>
#include <iterator>
int i = 0;
std::vector<int> elements{4, 0}; // elements = {0, 0, 0, 0}
for (auto it = elements.begin(); it < elements.end(); ++it) {
*it = ++i;
}
// elements = {1, 2, 3, 4}
Macros
Can be used to create slightly redundant function signatures or in modules like tests. The following macros contains 31 lines of code (LOC) and replaces 392 (LOC).
// For each function replace mentions of:
// N with {1-7} and
// M with {1-7}
// gives 49 functions with 8 lines of code each
// gives 392 lines of code
std::string GetFooNM(int& foo_value) {
std::string value = DoSomething(foo_value);
DoOtherStuff(&value);
if (value == "foo") {
return N;
} else {
return M;
}
}
std::string GetBarNM(const int& bar_value) {
std::string value = DoSomething(bar_value);
DoOtherStuff(&value);
if (value == "foo") {
return N;
} else {
return M;
}
}
int GetBazNM(std::string_view baz1_value, int baz2_value) {
std::string value = DoSomething(baz1_value);
DoOtherStuff(&value);
if (value == "foo") {
return N;
} else {
return M;
}
}
// Allows for variadic macros with no arguments.
#define VA_ARGS(...) , ##__VA_ARGS__
#define GET_DECL_NM(n, m, return_type, func_name, ...) \
int Get##func_name##n##m(VAR_ARGS) { \
std::string value = DoSomething(VAR_ARGS(__VA_ARGS__)); \
DoOtherStuff(&value); \
if (value == "foo") { \
return n; \
} else { \
return m; \
}
#define GET_DECL_N(m, return_type, func_name, ...) \
return_type func_name##1##m(VAR_ARGS(__VA_ARGS__)); \
return_type func_name##2##m(VAR_ARGS(__VA_ARGS__)); \
return_type func_name##3##m(VAR_ARGS(__VA_ARGS__)); \
return_type func_name##4##m(VAR_ARGS(__VA_ARGS__)); \
return_type func_name##5##m(VAR_ARGS(__VA_ARGS__)); \
return_type func_name##6##m(VAR_ARGS(__VA_ARGS__)); \
return_type func_name##7##m(VAR_ARGS(__VA_ARGS__));
#define GET_DECL(return_type, func_name, ...) \
GET_DEC_N(1. return_type, func_name, ...); \
GET_DEC_N(2. return_type, func_name, ...); \
GET_DEC_N(3. return_type, func_name, ...); \
GET_DEC_N(4. return_type, func_name, ...); \
GET_DEC_N(5. return_type, func_name, ...); \
GET_DEC_N(6. return_type, func_name, ...); \
GET_DEC_N(7. return_type, func_name, ...);
GET_DECL(std::string, Foo int& foo_value);
GET_DECL(std::string, Bar, const int& foo_value);
GET_DECL(std::string, Baz, std::string_view baz1_value, int baz2_value);
#undef GET_DECL
#undef GET_DECL_N
#undef VA_ARGS
Protocol Buffers
Differencer
#include <google/protobuf/util/message_differencer.h>
Proto proto1 = /* ... */;
Proto proto2 = /* ... */;
bool is_equal = google::protobuf::util::MessageDifferencer::Equals(&proto1, &proto2);
Repeated Fields
#include <google/protobuf/repeated_field.h>
Proto message;
message.add_int32_fields(1);
message.add_int32_fields(2);
message.add_int32_fields(3);
void Add(google::protobuf::RepeatedPtrField<Proto> int32_fields) {
int32_fields.Add(4);
int32_fields.Add(5);
}
google::protobuf::RepeatedPtrField<Proto> int32_fields = message.mutable_int32_fields();
Add(int32_fields);
// message.int32_fields = {1, 2, 3, 4, 5}
Parse File
#include <google/protobuf/text_format.h>
#include <fstream>
#include <iostream>
std::string proto_text;
std::ifstream my_file;
my_file.open("/dir/file.text_proto");
my_file >> proto_text;
Proto proto;
const bool parsed = google::protobuf::TextFormat().ParseFromString(proto_text, &proto);
Parse Text
#include <google/protobuf/text_format.h>
std::string_view proto_text = R"pb({ foo: "test_foo1" bar: "test_bar1" })pb";
Proto proto;
const bool parsed = google::protobuf::TextFormat().ParseFromString(proto_text, &proto);
#include <google/protobuf/text_format.h>
#include <string_view>
Proto proto;
std::string_view proto_text = R"pb({ foo: "test_foo1" bar: "test_bar1" })pb";
bool success1 = google::protobuf::TextFormat::ParseFromString(proto_text, &proto);
std::string_view proto_text_view =
R"pb({ foo: "test_foo1" bar: "test_bar1" })pb";
bool success2 = google::protobuf::TextFormat::ParseFromStringPiece(proto_text_view,
&proto);
Random
C++ Reference: Random - For a complete listing of different distributions.
WARNING: The following are not cryptographically secure.
#include <random>
// Other RNGs can also be defined instead.
std::default_random_engine rng;
// Random signed int32 interval [1, 2^31)
std::uniform_int_distribution<int> distribution(1, 1 << 31);
int x = distribution(rng);
// Random signed int32 interval [2, 10).
std::uniform_int_distribution<int> distribution(2, 10);
int y = distribution(rng);
// Random bool weighted 75% true and 25% false.
std::bernoulli_distribution distribution(0.75);
bool x = distribution(rng);
Strings
Case
C++ Reference: tolower
C++ Reference: toupper
#include <cctype>
#include <string_view>
std::string_view text = "Foo";
std::tolower(text); // -> foo
std::toupper(text); // -> FOO
Concatenate
#include <string>
#include <string_view>
std::string_view text = "cat" + "this" + "together";
Contains
#include <string>
#include <string_view>
std::string_view text = "foo bar baz";
const std::size_t pos = text.find("foo");
const bool found = pos != std::string::npos;
Format
C++ Reference: #print# functions
#include <cstdio>
std::printf("%c", 32) // Character = " "
std::printf("%s", "foo") // String = "foo"
std::printf("%02d", 1) // Decimal = "01"
std::printf("%o", 16) // Octal = "20"
std::printf("%#x", 0x16) // Hex = "0x16"
std::printf("%X", 10) // Hex = "A"
std::printf("%05.2f", 1.6) // Floating Point = "01.60"
std::printf("%e", 1.6) // Scientific = "1.600000e+00"
std::printf("%p", ptr) // Pointer = "0x7ffdeb6ad2a4"
#include <format>
#include <string>
// text = "x = 1, y = 2.0, z = "z""
const std::string text = std::format("x = {}, y = {}, z = {}", 1, 2.0, "z");
Join
#include <string>
#include <string_view>
#include <vector>
std::vector<std::string> words{"foo", "bar", "baz"};
std::string_view delimiter = "--";
std::string joined;
for (int i = 0; i < words.size() - 1; ++i) {
joined.append(words[i]);
joined.append(delimiter);
}
joined.append(words[words.size()-1]);
Replace
#include <string>
#include <string_view>
std::string text = "foo bar foo baz";
std::string_view target = "foo";
std::string_view replacement = "qux";
std::size_t pos = text.find(foo);
while (pos != std::string::npos) {
text = text.replace(pos, target.size(), replacement);
pos = text.find(foo);
}
RegEx
#include <regex>
std::regex re(R"(([A-Z][a-z]+) ([A-Z][a-z]+)");
std::smatch matches; // alias to std::match_results<string::const_iterator>
std::regex_match("Theodore Smiley", matches, re); // = true
// matches = {"Theodore Smiley", "Theodore", "Smiley"}; // First one is the full match.
std::regex_match("Theodore Smiley II", matches, re); // = false; must be a full match.
#include <regex>
std::regex re(R"(([A-Z][a-z]+) ([A-Z][a-z]+)");
std::smatch matches; // alias to std::match_results<string::const_iterator>
std::regex_search("Theodore Smiley II", matches, re); // = true
// matches = {"Theodore Smiley", "Theodore", "Smiley"}; // First one is the full match.
std::regex_search("Theodore", matches, re); // = false; must match the whole RegEx.
std::regex_search("Theodore Louis Tenacious Smiley II", matches, re); // = true
// matches = {"Theodore Louis", "Theodore", "Louis"}; // Only matches for one found.
Split
#include <string_view>
#include <vector>
std::string_view text = "foo::bar::::baz";
std::string_view delimiter = "::";
std::vector<std::string_view> elements;
std::size_t start = 0;
std::size_t end = text.find(delimiter);
while (end != std::string::npos) {
elements.push_back(text.substr(start, end - start));
start = end + delimiter.size();
end = text.find(delimiter, start);
}
elements.push_back(text.substr(start)); // {"foo", "bar", "", "baz"}
Starts With
#include <string_view>
std::string_view text = "foo/bar";
const bool starts_with = text.rfind("foo", 0) == 0;
String View Materialize
#include <string>
#include <string_view>
void DoSomething(std::string_view text);
auto materialized = std::string(text); // Materialize to a string copy.
Strip Prefix
#include <string>
#include <string_view>
std::string_view text = "foo/bar";
std::string_view prefix = "foo";
std::string_view stripped = text.rfind(prefix, 0) ? text : text.substr(0, prefix.length);
Structs
struct Point {
int x;
int y;
};
struct Point p = {1, 2};
struct Point p = {.y = 2, .x = 2};
The operator overloading below can be applied to classes as well. See the Syntax section of the C++ Reference: Operators Syntax section for an exhaustive list.
struct Point {
int x;
int y;
struct Point& operator+(const Point& rhs){
x += rhs.x;
y += rhs.y;
return *this;
}
struct Point& operator++(){
x++;
y++;
return *this;
}
struct Point& operator+=(const Point& rhs) {
x += rhs.x;
y += rhs.y;
return *this;
}
struct Point& operator+=(const int& value) {
x += value;
y += value;
return *this;
}
struct Point operator()(int value) {
return {value, value};
}
// Apply the same idea for
// -, --, -=
// *, *=
// /, /=
// etc.
};
Unpack
struct Packed {
int x;
char y;
float z;
};
Packed p = /* ... */;
// access by reference
auto & [ x, y, z ] = p;
// access by move
auto && [ xx, yy, zz ] = p;
Templates
template <class T>
T DoSomething(T a, T b) {
// ...
}
The definitions below will expand out the functions as needed from code.
template<typename T>
T Add(T v) {
return v;
}
template<typename T, typename... Ts>
T Add(T first, Ts... args) {
return first + Add(args...);
}
Time
#include <chrono>
std::chrono::system_clock::time_point current = std::chrono::system_clock::now();
#include <chrono>
#include <ctime>
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t time_now = std::chrono::system_clock::to_time_t(now);
// or ...
std::time_t time_now = std::time(nullptr);
std::ctime(&time_now); // -> Tue Jul 7 12:00:01 2020 (UTC)
std::asctime(std::localtime(time_now)); // -> Tue Jul 7 08:00:01 2020 (Local)
// https://en.cppreference.com/w/cpp/chrono/c/strftime
char time_text[80]; // Arbitrary but made to cover any possible string length for time.
std::strftime(time_text, 80, "%Y-%m-%d", time_now); // -> 2020-07-07
std::strftime(time_text, 80, "%Y-%m-%d %H:%M:%S", time_now); // -> 2020-07-07 23:50:02
std::strftime(time_text, 80, "%Y-%m-%dT%H:%M:%S", time_now); // -> 2020-07-07T23:50:02Z (ISO 8601 UTC)
std::strftime(time_text, 80, "%Y-%m-%dT%H:%M:%S %Z", time_now); // -> 2020-07-07T23:50:02 +02
std::strftime(time_text, 80, "%A, %B %e, %Y", time_now); // -> Monday, July 7, 2020
#include <ctime>
#include <time.h>
std::time_t time_now = std::time(nullptr);
std::localtime(&time_now);
// or for GMT ...
std::gmtime(&time_now);
// https://en.cppreference.com/w/c/chrono/tm
//
// All below are numerics.
struct tm* time = std::localtime(&time_now);
time->tm_year; // Year
time->tm_mon; // Month
time->tm_mday; // Day of Month
time->tm_wday; // Day of Week
// ...
Tuple
Unpack
auto tuple = std::make_tuple(1, 'a', 2.3);
const auto [a, b, c] = tuple;
// Same goes for arrays.
std::array<int, 3> arr{1, 2, 3};
auto [x, y ,z] = arr;
Unique Pointer
#include <memory>
auto my_object_ptr1 =
std::make_unique(new MyObject(myobject_ctor_arg1, myobject_ctor_arg2));
auto my_object_ptr2 =
std::make_unique<MyObject>(myobject_ctor_arg1, myobject_ctor_arg2);
#include <memory>
auto int_ptr1 = std::make_unique<MyObject>();
int_ptr1.reset(); // Delete wrapped pointer.
auto int_ptr2 = std::make_unique<MyObject>();
int_ptr1.release(); // Release control of pointer.
Vector
Concat
#include <vector>
std::vector<int> v1{1, 2, 3};
std::vector<int> v2{4, 5, 6};
v1.insert(v1.end(), v2.begin(), v2.end());
Iterate
#include <vector>
std::vector<int> v = {1, 2};
for(int i=0; i < v.size(); i++) {
int x = v[i]
}
for(int x : v) {
int y = x;
}
Copy
#include <vector>
std::vector<int> from = {1, 2};
std::vector<int> to(from.begin(), to.end());
Appends
#include <vector>
std::vector<int> v1 = {1, 2};
std::vector<int> v2 = {3, 4};
v1.insert(v1.end(), v2.begin(), v2.end());
Leave a comment