Show Menu
Cheatography

Modern C++ 17 Standard Library Features Cheat Sheet by

New features included in the C++ 17 Standard Library

std::v­ariant

std::variant<int, double> v {12};
std::get<int>(v); // == 12
std::get<0>(v); // == 12
v = 12.0;
std::get<double>(v); // == 12.0
std::get<1>(v); // == 12.0
The class template std::v­ariant represents a type-safe union. An instance of std::v­ariant at any given time holds a value of one of its altern­ative types (it's also possible for it to be valuel­ess).

std::o­ptional

std::optional<std::string> create(bool b) {
  if (b) {
    return "Wonder Woman";
  } else {
    return {};
  }
}

create(false).value_or("empty"); // == "empty"
create(true).value(); // == "Wonder Woman"
// optional-returning factory functions are usable as conditions of while and if
if (auto str = create(true)) {
  // ...
}
The class template std::o­ptional manages an optional contained value, i.e. a value that may or may not be present. A common use case for optional is the return value of a function that may fail.

std::any

std::any x {5};
x.has_value() // == true
std::any_cast<int>(x) // == 5
std::any_cast<int&>(x) = 10;
std::any_cast<int>(x) // == 10
A type-safe container for single values of any type.

std::s­tri­ng_view

// Regular strings.
std::string_view cppstr {"foo"};
// Wide strings.
std::wstring_view wcstr_v {L"baz"};
// Character arrays.
char array[3] = {'b', 'a', 'r'};
std::string_view array_v(array, std::size(array));

std::string str {"   trim me"};
std::string_view v {str};
v.remove_prefix(std::min(v.find_first_not_of(" "), v.size()));
str; //  == "   trim me"
v; // == "trim me"
A non-owning reference to a string. Useful for providing an abstra­ction on top of strings (e.g. for parsing).

Parallel algorithms

std::vector<int> longVector;
// Find element using parallel execution policy
auto result1 = std::find(std::execution::par, std::begin(longVector), std::end(longVector), 2);
// Sort elements using sequential execution policy
auto result2 = std::sort(std::execution::seq, std::begin(longVector), std::end(longVector));
Many of the STL algori­thms, such as the copy, find and sort methods, started to support the parallel execution policies: seq, par and par_unseq which translate to "­seq­uen­tia­lly­", "­par­all­el" and "­par­allel unsequ­enc­ed".
 

std::i­nvoke

template <typename Callable>
class Proxy {
  Callable c;
public:
  Proxy(Callable c): c(c) {}
  template <class... Args>
  decltype(auto) operator()(Args&&... args) {
    // ...
    return std::invoke(c, std::forward<Args>(args)...);
  }
};
auto add = [](int x, int y) {
  return x + y;
};
Proxy<decltype(add)> p {add};
p(1, 2); // == 3
Invoke a Callable object with parame­ters. Examples of Callable objects are std::f­unction or std::bind where an object can be called similarly to a regular function.

std::apply

auto add = [](int x, int y) {
  return x + y;
};
std::apply(add, std::make_tuple(1, 2)); // == 3
Invoke a Callable object with a tuple of arguments.

std::f­ile­system

const auto bigFilePath {"bigFileToCopy"};

if (std::filesystem::exists(bigFilePath)) {
  const auto bigFileSize {std::filesystem::file_size(bigFilePath)};
  std::filesystem::path tmpPath {"/tmp"};

  if (std::filesystem::space(tmpPath).available > bigFileSize) {
    std::filesystem::create_directory(tmpPath.append("example"));
    std::filesystem::copy_file(bigFilePath, tmpPath.append("newFile"));
  }
}
The new std::f­ile­system library provides a standard way to manipulate files, direct­ories, and paths in a filesy­stem.

Here, a big file is copied to a temporary path if there is available space.
 

std::byte

std::byte a {0};
std::byte b {0xFF};
int i = std::to_integer<int>(b); // 0xFF
std::byte c = a & b;
int j = std::to_integer<int>(c); // 0
The new std::byte type provides a standard way of repres­enting data as a byte. Benefits of using std::byte over char or unsigned char is that it is not a character type, and is also not an arithmetic type; while the only operator overloads available are bitwise operat­ions.

Note that std::byte is simply an enum, and braced initia­liz­ation of enums become possible thanks to direct­-li­st-­ini­tia­liz­ation of enums.

Splicing for maps and sets

// Moving elements from one map to another:
std::map<int, string> src {{1, "one"}, {2, "two"}, {3, "Three"}};
std::map<int, string> dst {{3, "three"}};
dst.insert(src.extract(src.find(1)));
dst.insert(src.extract(2)); 
// dst == { { 1, "one" }, { 2, "two" }, { 3, "three" } };

// Inserting an entire set:
std::set<int> src {1, 3, 5};
std::set<int> dst {2, 4, 5};
dst.merge(src);
// src == { 5 }
// dst == { 1, 2, 3, 4, 5 }

// Inserting elements which outlive the container:
auto elementFactory() {
  std::set<...> s;
  s.emplace(...);
  return s.extract(s.begin());
}
s2.insert(elementFactory());

// Changing the key of a map element:
std::map<int, string> m {{1, "one"}, {2, "two"}, {3, "three"}};
auto e = m.extract(2);
e.key() = 5;
m.insert(std::move(e));
// m == { { 1, "one" }, { 3, "three" }, { 5, "two" } }
Moving nodes and merging containers without the overhead of expensive copies, moves, or heap alloca­tio­ns/­dea­llo­cat­ions.
       
 

Comments

No comments yet. Add yours below!

Add a Comment

Your Comment

Please enter your name.

    Please enter your email address

      Please enter your Comment.

          Related Cheat Sheets

          C++ Pointers cookbook Cheat Sheet

          More Cheat Sheets by NexWebSites

          Basic Linux Commands Cheat Sheet