Modern C++ Workshop

Day 1 - Overview

Agenda

  • Monday, September 5th
    • overview
    • auto type deduction
  • Tuesday, September 6th
    • new class definition features
  • Wednesday, September 7th
    • STL containers and algorithms
  • Thursday, September 8th
    • memory management and move semantics
  • Friday, September 9th
    • concurrency
    • exceptions
  • Monday, September 12th
    • Q&A and topics you'd like to dig deeper into

Disclaimer

This is a 10000 ft overview. Don't expect to fully grasp everything.

 

Follow up sessions will repeat everything and drill much further into details.

 

Some of the material presented is opinionated.

 

It's really helpful to look at assembly using http://gcc.godbolt.org/

C++11 + 14 + 17

  • rethinking c++
  • strong backwards compatibility
  • catch-up with newer languages
  • many more things you shouldn't do
    • even more than before
    • some things that were considered best practice before
  • much higher developer productivity!

Major new features of modern C++

  • auto type deduction
  • range-based for loops
  • lambda functions
  • new STL algorithms and containers
  • nullptr and nullptr_t
  • move semantics
  • memory management library
  • allocator traits
  • threading and parallelism library
  • variadic templates
  • decltype

auto type deduction

// typeof(connection)
// is std::shared_ptr<Connection>
auto connection =
  std::make_shared<Connection>();

// typeof(sum) is int
auto sum = 3 + 4;

// typeof(ratio) is double
auto ratio = sum / 4.0

range based for loops

auto numbers =
        {1,7,8,12,4,9};

for(const auto& n : numbers) {
    std::cout
          << n
          << std::endl;
}

lambda functions

std::vector<int> numbers = {1,4,19};

// find the first n > 8 in vector
auto number =
    std::find_if(
        numbers.begin(),
        numbers.end(),
        [](const auto& n) {
            return n > 8;
        });

// remove even numbers
numbers.erase(
    std::remove_if(
        numbers.begin(),
        numbers.end(),
        [](const auto& n) {
            return n % 2 == 0;
        }));

STL Containers

Hash based containers std::unordered_set and std::unordered_map provide average O(1) lookups and inserts.

 

std::array should replace C-style arrays for most use cases.

 

std::tuple can contain tuples of arbitrary types

STL Algorithms

Lambdas now can be used in algorithms where applicable.

 

Numerous new algorithms have been added:

all_of, any_of, none_of, find_if_not, copy_if, copy_n, move, move_backward, shuffle, is_partitioned, partition_copy, partition_point, is_sorted, is_sorted_until,

is_heap, is_heap_until, minmax, minmax_element, is_permutation, iota, uninitialized_copy_n

 

Containers have new operations like emplace, shrink_to_fit

nullptr and nullptr_t

 

Gets rid of dangerous ambiguities like the following:

std::string s1( false ); // compiles, calls char* constructor with null
std::string s2( true );  // error

move semantics

New resource management feature serving two purposes:

1. Gain performance by avoiding copies

std::string oneTerabyteString = fillOneTerabyteString();
std::vector<std::string> myStrings;
mystrings.push_back(std::move(oneTerabyteString));
// terabytes of data have not been copied

2. Enforce semantic correctness by permitting resource transfer while forbidding copies

void consumeResource(std::unique_ptr<Resource> resource) {
    doSomeThingWith(*resource);
}

// resource is allocated
auto uniqueResource = std::make_unique<Resource>();
consumeResource(std::move(uniqueResource));
// resource is freed in consumeResource

memory management

std::shared_ptr and std::weak_ptr behave like their boost cousins.

 

std::unique_ptr cannot been copied, but can be transferred via move. This enables safe and performant memory management by restricting ownership to one owner.

allocator traits

std::allocator_traits provide reasonable defaults for most allocator operations and make creating your own allocators viable in a many more situations

threading and parallelism

thread_local keyword enables thread local storage.

 

std::thread, std::mutex, std::lock_guard, std::atomic offer a similar API to boost

 

std::promise and std::future offer higher-level syncronization primitives

Thanks!

Questions?

variadic templates

// stolen from facebook::folly
template <typename T, typename... Ts>
size_t hash_combine(const T& t, const Ts&... ts) {
  size_t seed = std::hash<T>()(t);
  if (sizeof...(ts) == 0) {
    return seed;
  }     
  // this is expanded + inlined at compile time
  size_t remainder = hash_combine(ts...);
  return hash_128_to_64(seed, remainder);
}

struct MyStruct {
  int x;
  std::string y;
  double z;

  size_t hash() {
    return hash_combine(x, y, z);
  }
};

decltype

#include <string>
using namespace std::string_literals;

template <typename T, typename U>
auto sum(T a, U b) -> decltype(a + b) {
    return a + b;
}

auto doubleSum = sum(5, 4.3);               // 9.3
auto stringSum = sum("hello "s, "world!"s); // "hello world!"

Modern C++ Workshop - Day 1

By Jupp Müller

Modern C++ Workshop - Day 1

  • 655