July 2022
#include <memory>
void func()
{
std::shared_ptr<int> ptr (new int(42));
if ( /* ... */ )
return; // no memory leak
}
Better:
Best:
auto p1 = std::make_shared<int>(1);
auto p2 = p1;
assert(*p2 == 1);
assert(p1.use_count() == 2);
auto p3 = std::make_unique<int>(2);
// auto p4 = p3; // unique_ptr can't be copied
auto p5 = std::move(p3);
assert(*p5 == 2);
assert(p3 == nullptr);
// auto p6 = std::weak_ptr<int>(3); // weak_ptr can't own
auto p6 = std::weak_ptr<int>(p1);
assert(p6.use_count() == 2);
p1.reset();
p2.reset();
assert(p6.expired());
Name | Description |
---|---|
array |
static contiguous array |
vector |
dynamic contiguous array |
list |
linked list |
set |
sorted collection of unique keys |
map |
sorted collection of key-value pairs |
unordered_set |
hashed collection of unique keys |
unordered_map |
hashed collection of key-value pairs |
concept
requires
co_await
co_return
co_yield
import
module
constinit
consteval
char8_t
// math.cppm
export module math;
export int add(int fir, int sec)
{
return fir + sec;
}
// client.cpp
import math;
int main()
{
add(2000, 20);
}
int f1() { return 1; } // A C-like function
int f2(int arg) { return arg; } // Function overloading
double f2(double arg) { return arg; }
template <typename T> // Function template
T f3(T arg) { return arg; }
struct F4 { // Functor
int operator()() { return 4; }
};
auto f5 = [] (int i) { return i * i; }; // Lambda (C++11)
auto f6 = [] (auto arg) { // Generic lambda (C++14)
return std::to_string(arg);
};
co_return
(coroutine return statement)co_await
(await expression)co_yield
(yield expression)Task<T>
: asynchronous computation that is executed lazilyGenerator<T>
: a coroutine type that produces a sequence of values of type T
where values are produced lazily and synchronously.enable_if
was used to check template arguments (Example).#include <algorithm>
int main()
{
std::vector<int> data{42, 1, 12, -3, 14, -5};
std::vector<int> pos;
// copy only positive numbers:
std::copy_if(data.begin(), data.end(),
std::back_inserter(pos), [](int i){ return i >= 0; });
}
range
is a concept, not a container<ranges>
:operator|
(see CompilerExplorer).auto const data = {0, 1, 2, 3, 4, 5};
auto even = [](const auto& v) { return 0 == v % 2; };
auto square = [](const auto& v) { return v * v; };
// "pipe" syntax of composing the views:
auto result { data
| std::views::filter(even)
| std::views::transform(square)
| std::views::drop(2)
| std::views::reverse
| std::views::transform([](const auto& v){ return std::to_string(v); }) };
template<class D>
requires std::is_class_v<D> && std::same_as<D, std::remove_cv_t<D>>
class view_interface;
view_interface
is typically used with CRTP
auto odd = [](int i){ return i % 2 == 1; };
auto isPrime = [](int i) {
for (int j=2; j*j <= i; ++j){
if (i % j == 0) return false;
}
return true;
};
for (int i: std::views::iota(1) | std::views::filter(odd)
| std::views::filter(isPrime)
| std::views::take(10))
{
std::cout << i << std::endl;
}
std::format
std::format("The answer is {}.", 42);
std::format("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
==
, <
contain the real logic!=
, >
, <=
, >=
will be derivedop(const& T1, const& T2)
op(const& T2, const& T1)
struct Point
{
int x,y;
friend bool operator == (const Point& a, const Point& b) {
return a.x == b.x and a.y == b.y; }
friend bool operator < (const Point& a, const Point& b) {
return a.x < b.x or (a.x == b.x and a.y < b.y); }
friend bool operator != (const Point& a, const Point& b) {
return !(a==b); }
friend bool operator <= (const Point& a, const Point& b) {
return !(b<a); }
friend bool operator > (const Point& a, const Point& b) {
return b<a; }
friend bool operator >= (const Point& a, const Point& b) {
return !(a<b); }
};
<=>
(similar to strcmp
)
operator ==
strong_ordering
<, >, ==
must be true and if a == b
then f(a) == f(b)
weak_ordering
(equivalent but not equal)
<, >, ==
must be true and if a == b
then f(a) != f(b)
CaseInsensitiveString
storing original string, but compare in case-insensitive way.partial_ordering
<, >, ==
might be true and if a==b
then f(a) != f(b)
NaN
is not comparable2016 Quali Round Problem B: Revenge of the Pancakes
Stack of pancakes with a happy face made of chocolate on one side ‘+’ and nothing on the other side ‘-’. Goal is to have all pancakes with the happy side on the top.
std::string stack{"++--+-"};
auto flip = [](const char c){
return c == '+' ? '-' : '+'; // Conditional/Ternary operator
};
int n = 0;
for (auto first = std::ranges::find(stack, '-'); first != std::end(stack);
first = std::ranges::find(stack, '-'), n++)
{
if (stack[0] == '+') {
auto sub = std::ranges::subrange(std::begin(stack), first);
std::ranges::transform(sub, std::begin(sub), flip);
} else {
auto first_happy = std::ranges::find(stack, '+');
auto sub = std::ranges::subrange(std::begin(stack), first_happy);
std::ranges::transform(sub, std::begin(sub), flip);
}
}
std::cout << "You need " << n << " flips to make all happy." << std::endl;
Ranges
is a great step towards functional programmingModules
simplifies multiple translation unitsConcepts
allows template arguments specificationsCoroutines
are stackless and can be suspendedReflections
and more ranges are expected for C++23C++20 (B. Doser)