Modern C++ Notes

Page Contents

Readable numbers - digit grouping

10'000; // Use apostrophe to group digits

Vectors

using std::vector;
...
vector numbers {0, 1, 2, 3}; // Note do not need template arg in C++17 - compiler will deduce - Class template argument deduction (CTAD)

// Push back - will COPY without std::move - we use std::move if we like.
numbers.push_back(4);

// Access using array style bracket operator
numbers[0] = 42;

// Range based for loop
for (auto i : numbers)
{
    // Do something with i
}

// Vectors like to COPY on resize - but they also MOVE if the contents are moveable.

Array

Does not grow. May be on the stack. Collection whose size is known at compile time.


List

Map

Multimap

Unordered Map / Multimap

Stack

Dequeue

Priority Queue

Lambdas

If assigning to a variable must declare that variable auto - there is no other option.

[] () -> return_type {}
^^ ^^ ^^ ^^^^^^^^^^^
^^ ^^ ^^ Return type is optional - compiler can try to deduce this
^^ ^^ Function body
^^ Function parameters
Capture clause
Makes variables from the calling scope usable in the the lambda
So when capture clause is empty the function will only work with the parameters passed into it.
If you capture by *value* ([foo, bar, ...]), they are *copied* into lambda.
    Use "mutable" to change the values of variables captures by value - note only changes the local copy though!
If you capture by *reference* ([&foo, &bar, ...]) no copies are made. Changes in the lambda to these variables will affect the originals.
    Beware *dangling reference dangers* here!
Capture by *alias* ([bar=foo+1, ...])
Capture by *move* ([x=std::move(bar), ...])
Capture everything in the calling scope that is specifically used by the lambda *by value* ([=])
Capture everything in the calling scope that is specifically used by the lambda *by reference* ([&])

Compiler will, behind the scenes, generate a function object using the code from the lambda. Usee C++ insights to see whats going on:

TODO show CPP insights tool use

Move Semantics

Chrono

Value type?

T::template value_type varname(..._)???

Movable stuff

Clever chap answered my questions here. Notes as I went along are:

Note: Deleting the move operators is not the same as as not defining them when a copy constructor/assignment is defined.

In the latter scenario the move functions are not implicitly defined by the compiler and because they dont exist, will not be considered in overload resolution. However, the object is still considered moveable by is_move_constructible_v et al because the copy constructor accepting a const reference can accept an R-value.

However, in the former scenario, when the move functions are explicitly deleted, the move functions can be considered in the overload resolution because deleted members are still declared. Deleted members participate in overload resolution. Members not present don't. Reason is this: Deleting of normal member function or nonmember functions prevents problematic type promotions from causing an unintended function to be called. This works because deleted functions still participate in overload resolution and provide a better match than the function that could be called after the types are promoted. See: https://learn.microsoft.com/en-us/cpp/cpp/explicitly-defaulted-and-deleted-functions

This leave me with the question, why was is_move_constructible defined this way? Why not make it only be true when there is a default or explicitly defiend move constructor? The answer is that is_move_constructible is just defined as the object can be constructed from an rvalue: how it's constructed doesn't matter. It's constructed by a copy constructor, or a move constructor, and how the constructor is implemented, like if it's actually doing a "move", doesn't matter