# C++

*C++ is history repeated as tragedy. Java is history repeated as farce.*

*If you like C++, you don’t know C++.*

*C++ is to C as Lung Cancer is to Lung.*

## BS

*Bjarne Stroustrup is a Trump-like populist and demagogue*. This explains everything about C++.

*C is C++ without the BS.*

*C++ is a language strongly optimized for liars and people who go by guesswork and ignorance.* It has been sold to them, like Java been sold to absolute idiots.

## C++17

C++ is a "nightmare" industry-standard *implementation language* to be used in a rare case when you are know *what* you are doing and *why* it is so, and when you already have a working prototype in some *prototyping language*. It is only suitable to re-implement something in C++ because you absolutely have to.

Use ONLY a small, sane subset of *c++17* standard along with Clang -- since c++11 has been actually implemented in `clang++`

it began to approach the borders of sanity.

Otherwise Go is a **much** better alternative (especially for prototyping), being an extraordinary well-crafted language. Everything which is *only claimed* to be good about C++ (expressiveness, static type checking, zero-overhead abstractions, etc.) is indeed better in Go.

## clang++ -std=c++17 -stdlib=libc++

Basically, at the time of conception of the first proposals B.S. was (and still is) a narcissistic fucking demagogue, ignorant of most of the current developments in functional languages. He is still a fucking demagogue.

However, literally millions of man-hours has been spent on improving C++ and the current C++17 standard along with clang++ compiler and libc++ C++17 standard library makes it finally usable (with a bit less pain).

int v[] = {0,1,2,3,4,5,6,7,8,9}; for (auto& x : v) ++x; for (auto& x : v) cout << x << "\n";

## How do we know it is any good?

LLVM/Clang (proves itself by example), Languages/Swift, Android/NDK, Chrome, Libs/Tensorflow and some crap from Facebook, like Tools/HHVM and Tools/PyTorch.

## Old plain C

This is an unsophisticated implementation of a `Single Linked List`

#include <stdio.h> #include <stdlib.h> struct list_node { struct list_node *prev, *next; int value; }; struct list { struct list_node *first, *last; }; void list_node_init(struct list_node *n, int v) { n->value = v; } struct list_node *list_advance(struct list_node *n) { return n->next; } struct list_node *list_begin(struct list *xs) { return xs->first; } struct list_node *list_end(struct list *xs) { return NULL; } void list_init(struct list *xs) { xs->first = NULL; xs->last = NULL; } void list_insert(struct list *xs, struct list_node *where, int v) { struct list_node *newnode = (struct list_node *)malloc(sizeof(*newnode)); list_node_init(newnode, v); newnode->prev = where ? where->prev : xs->last; newnode->next = where; if (newnode->prev) newnode->prev->next = newnode; if (where) where->prev = newnode; if (where == xs->first) xs->first = newnode; if (!where) xs->last = newnode; } void list_push_front(struct list *xs, int v) { list_insert(xs, list_begin(xs), v); } void list_push_back(struct list *xs, int v) { list_insert(xs, list_end(xs), v); } void list_erase(struct list *xs, struct list_node *where) { struct list_node *prev = where->prev; struct list_node *next = where->next; if (prev) prev->next = next; if (next) next->prev = prev; if (where == xs->first) xs->first = next; if (where == xs->last) xs->last = prev; free(where); } void list_clear(struct list *xs) { while (xs->first) list_erase(xs, xs->first); } void list_done(struct list *xs) { list_clear(xs); } int main(void) { struct list xs; struct list_node *n; list_init(&xs); list_push_back(&xs, 1); list_push_back(&xs, 5); list_push_front(&xs, 8); list_push_back(&xs, 3); for (n = list_begin(&xs); n != list_end(&xs); n = list_advance(n)) { printf("%d", n->value); } printf("\n"); list_done(&xs); return 0; }

The big idea of original `C++`

was to *improve* `C`

with better *types* in the first place, and adding OO features, such as *classes*, was only part of the process.

### Zero cost abstractions meme

What is more important, there was the principle of re-using a mature and battle-tested `C`

*compiler* whenever possible, so classes were packed as structs, methods were merely ordinary function calls with one extra (-1) argument (single extra pointer allocation on a stack), etc.

Compilers suites, such as `gcc`

or Clang would generate almost exactly the same machine code for `C`

and `C++`

version of the *translated* code, like in the example below:

### the smallest sane subset of C++

This is an example of a sane, Rust-like C++. *Nested structure* (**NOT** classes yet), *constructors* and *destructors*, the `new`

keyword, typed references (`(T &)`

,

struct list { struct node { node *prev, *next; int value; node(int v) { value = v; } node *advance() { return next; } }; node *first, *last; node *begin() { return first; } node *end() { return NULL; } list() { first = NULL; last = NULL; } ~list() { clear(); } void insert(node *where, int v) { node *newnode = new node(v); newnode->prev = where ? where->prev : last; newnode->next = where; if (newnode->prev) newnode->prev->next = newnode; if (where) where->prev = newnode; if (where == first) first = newnode; if (!where) last = newnode; } void push_front(int v) { insert(begin(), v); } void push_back(int v) { insert(end(), v); } void erase(node *where) { node *prev = where->prev; node *next = where->next; if (prev) prev->next = next; if (next) next->prev = prev; if (where == first) first = next; if (where == last) last = prev; delete where; } void clear() { while (first) erase(first); } };

### Templates

The original idea was not that bad - generate *copies* of the same code for each *instantiated* type and call efficiently it via a single "table look up". The binary becomes fat, but the code is still fast and straightforward.

The *real* problems of C++ began when they lost the track of this sane, relatively simple, understandable, straightforward *C++ -> C -> Assembly -> ABI calls* pipeline.

template <typename T> struct list { struct node { node *prev, *next; T value; node(T v) { value = v; } node *advance() { return next; } }; node *first, *last; node *begin() { return first; } node *end() { return NULL; } list() { first = NULL; last = NULL; } ~list() { clear(); } void insert(node *where, T v) { node *newnode = new node(v); newnode->prev = where ? where->prev : last; newnode->next = where; if (newnode->prev) newnode->prev->next = newnode; if (where) where->prev = newnode; if (where == first) first = newnode; if (!where) last = newnode; } void push_front(T v) { insert(begin(), v); } void push_back(T v) { insert(end(), v); } void erase(node *where) { node *prev = where->prev; node *next = where->next; if (prev) prev->next = next; if (next) next->prev = prev; if (where == first) first = next; if (where == last) last = prev; delete where; } void clear() { while (first) erase(first); } };

and then

list<int> xs;

**Note:**See TracWiki for help on using the wiki.