Part I
int fact(int x) {
    return (x <= 2)
        ? 1
        : fact(x - 1) + fact(x - 2);
}int fact(int x) {
    int n = 1, i = 2;
    for (; i <= x; ++i) {
        n *= i;
    }
    return n;
}Imperative
Declarative
    int n = 1;
loop:
    int i = 2;
    n *= i;
    ++i;
    if (i > 10) return n;
    // no loop, only goto
    goto loop;int fact(int x) {
    // variables on top
    int n = 1, i = 2;
    // for loop
    for (; i <= x; ++i) {
        n *= i;
    }
    return n; // single return
}
int n = fact(10);Unstructured
Structured
// modifies parameter, has side effects
void procedural(std::vector<int>& nums) {
    // sequentially executed procedures
    std::erase_if(nums, [&](int x){ return x % 2 == 0; });
    std::ranges::sort(nums);
    std::ranges::for_each(nums, [&](int& x) { x += nums.size(); });
}// no side effects, returns result
std::vector<int> functional(const std::vector<int>& nums) {
    // nested function invocation
    return for_each(
        sort(
            erase_if(
                nums,
                [&](int x){ return x % 2 == 0; }
            )
        ),
        [&](int& x){ return x % 2 == 0; }
    );
}(Procedural)
(Functional)
template<typename T, typename Func>
T helper(T input, Func&& func) {
    func(input);
    return input;
}
template<typename T, typename Func>
T for_each(const T& input, Func&& func) {
    return helper(
        input,
        [&](T& input){ 
            std::ranges::for_each(input, func);
        }
    );
}
template<typename T, typename Func>
T erase_if(const T& input, Func&& func) {
    return helper(
        input,
        [&](T& input){ 
            std::erase_if(input, func);
        }
    );
}
template<typename T>
T sort(const T& input) {
    return helper(
        input,
        [&](T& input){ 
            std::ranges::sort(input);
        }
    );
}// modifies parameter, has side effects
void procedural(std::vector<int>& nums) {
    // sequentially executed procedures
    std::erase_if(nums, [&](int x){ return x % 2 == 0; });
    std::ranges::sort(nums);
    std::ranges::for_each(nums, [&](int& x) { x += nums.size(); });
}// no side effects, returns result
std::vector<int> functional(const std::vector<int>& nums) {
    // nested function invocation
    return for_each(
        sort(
            erase_if(
                nums,
                [&](int x){ return x % 2 == 0; }
            )
        ),
        [&](int& x){ return x % 2 == 0; }
    );
}(Procedural)
(Functional)
Procedural
Object oriented
Imperative
Functional
Declarative
private implementation
public interface
Object
Object
Object
Object
Object
Object
Object
Object
Object
class Dictionary {
private:
  // complex data structures
  // hidden from user
public:
  // stable interface 
  // regardless of implementation
  Value find(Key);
  void insert(Key, Value);
  void erase(Key);
}s
private implementation
public interface
Object
Object
Object
Object
Object
Object
Object
Object
Object
messages
mood, thoughts, ...
Anna
Jerry
Tom
Bob
Century Bank
MasterBank
Your Vault
Mall ATM 2
Mall ATM 1
talk
cheer
deposit
transfer
balance
withdraw
talk
cheer
...
fields (data members)
methods (member functions)
private
public
fields (data members)
methods (member functions)
class Person {
private:
    std::map<Emotion, Strength> mood;
    std::vector<Thaught> mind;
    ...
public:
    void cheer(float strength) {
        mood.at("happy").increase(strength);
        ...
    }
    ...
};class Triangle {
public:
    float base, height;
    // does not modify object
    // can be called on a const Triangle
    float area() const {
        return base * area / 2.0;
    }
    
    // potentially modifies object
    // cannot be called on a const Triangle
    float scale(float factor) {
        base *= scale;
        height *= scale;
    }
};const Triangle t{2.0, 3.0};
t.area(); // ok
t.base = 3.0; // error
t.scale(4.0); // errorTriangle t{2.0, 3.0};
t.area(); // ok
t.base = 3.0; // ok
t.scale(4.0); // okclass Triangle {
public:
    float base, height;
    float area(/* const Triangle* this */) const {
        return this->base * this->area / 2.0;
    }
    
    float scale(/* Triangle* this, */ float factor) {
        this->base *= scale;
        this->height *= scale;
    }
};class Triangle {
public:
    float base, height;
    float area() const {
        return base * area / 2.0;
    }
    float scale(float factor) {
        base *= scale;
        height *= scale;
    }
    
    void swap(Triangle& other) {
        if (this == &other)
            return;
        std::swap(base, other.base);
        std::swap(height, other.height);
    }
};class Circle {
private:
    static constexpr float PI = 3.141592653;
    
    static hypot2(float x, float y) {
        return x * x + y * y;
    }
public:
    float radius;
    
    float area() const {
        return PI * radius * radius;
    }
    float circumference() const {
        return 2.0 * PI * radius;
    }
    bool contains(float x, float y) const {
        return hypot2(x, y) <= radius * radius;
    }
    
    void swap(Circle& other) {
        std::swap(radius, other.radius);
    }
    static void swap(Circle& lhs, Circle& rhs) {
        lhs.swap(rhs);
    }
};Circle c1{2.0}, c2{3.0};
Circle::swap(c1, c2);class Point {
private:
    // ...
public:
    static Point fromPolar(double angle, double radius);
    static Point fromCartesian(double x, double y);
    double x() const;
    void x(double newX);
    double y() const;
    void y(double newY);
    double angle() const;
    void angle(double newAngle);
    double radius() const;
    void radius(double newRadius);
};class Point {
private:
    // ...
public:
    [[nodiscard]] constexpr static Point fromPolar(double angle, double radius) noexcept;
    [[nodiscard]] constexpr static Point fromCartesian(double x, double y) noexcept;
    [[nodiscard]] constexpr double x() const noexcept;
    constexpr void x(double newX) noexcept;
    [[nodiscard]] constexpr double y() const noexcept;
    constexpr void y(double newY) noexcept;
    [[nodiscard]] constexpr double angle() const noexcept;
    constexpr void angle(double newAngle) noexcept;
    [[nodiscard]] constexpr double radius() const noexcept;
    constexpr void radius(double newRadius) noexcept;
};class Point {
private:
    double _x, _y;
public:
    static Point fromPolar(double angle, double radius) {
        Point p;
        p._x = sin(angle) * radius;
        p._y = cos(angle) * radius;
        return p;
    }
    static Point fromCartesian(double x, double y) {
        Point p;
        p._x = x;
        p._y = y;
        return p;
    }
    double x() {
        return _x;
    }
    void x(double newX) {
        _x = newX;
    }
    double y() {
        return _y;
    }
    void y(double newY) {
        _y = newY;
    }
    double angle() {
        return atan2(_y, _x);
    }
    void angle(double newAngle) {
        (*this) = fromPolar(newAngle, radius());
    }
    double radius() {
        return hypot(_x, _y);
    }
    void radius(double newRadius) {
        (*this) = fromPolar(angle(), newRadius);
    }
};class Point {
private:
    double _angle, _radius;
public:
    static Point fromPolar(double angle, double radius) {
        Point p;
        p._angle = angle;
        p._radius = radius;
        return p;
    }
    static Point fromCartesian(double x, double y) {
        Point p;
        p._angle = atan2(y, x);
        p._radius = hypot(x, y);
        return p;
    }
    double x() {
        return sin(_angle) * _radius;
    }
    void x(double newX) {
        (*this) = fromCartesian(newX, y());
    }
    double y() {
        return cos(_angle) * _radius;
    }
    void y(double newY) {
        (*this) = fromCartesian(x(), newY);
    }
    double angle() {
        return _angle;
    }
    void angle(double newAngle) {
        _angle = newAngle;
    }
    double radius() {
        return _radius;
    }
    void radius(double newRadius) {
        _radius = newRadius;
    }
};class Point {
private:
    double _x, _y;
public:
    [[nodiscard]] constexpr static Point fromPolar(double angle, double radius) noexcept {
        Point p{};
        p._x = sin(angle) * radius;
        p._y = cos(angle) * radius;
        return p;
    }
    [[nodiscard]] constexpr static Point fromCartesian(double x, double y) noexcept {
        Point p{};
        p._x = x;
        p._y = y;
        return p;
    }
    [[nodiscard]] constexpr double x() const noexcept {
        return _x;
    }
    constexpr void x(double newX) noexcept  {
        _x = newX;
    }
    [[nodiscard]] constexpr double y() const noexcept   {
        return _y;
    }
    constexpr void y(double newY) noexcept  {
        _y = newY;
    }
    [[nodiscard]] constexpr double angle() const noexcept   {
        return atan2(_y, _x);
    }
    constexpr void angle(double newAngle) noexcept  {
        (*this) = fromPolar(newAngle, radius());
    }
    [[nodiscard]] constexpr double radius() const noexcept  {
        return hypot(_x, _y);
    }
    constexpr void radius(double newRadius) noexcept  {
        (*this) = fromPolar(angle(), newRadius);
    }
};sizeof(name)
alignof(name)
decltype(name)
name
#name.................sizealigmentstorage durationtypevaluenamelifetime(different than typeid(name))
(optional)
(may be undefined)
.................automatic
dynamic
thread
static
automatic
dynamic
thread
static
automatic
dynamic
thread
static
some_t global_var; // static
extern some_t defined_elsewhere_var; // automatic
void f() {
    int x; // automatic
    static int y; // static
}int counter() {
    static int value = 0;
    return value++; 
}
int main() {
    for (int i = 0; i < 10; ++i) {
        std::cout << counter();
        // 0 1 2 3 4 5 6 7 8 9 
    }
}automatic
dynamic
thread
static
type* ptr = new type;
type* ptr = new type(init-args);
type* ar = new type[size];
type* ar = new type[size](init-args);
delete ptr;
delete[] ar;
automatic
dynamic
thread
static
// transfers ownership
int* multiplesOfThree(int count) {
    int* ar = new int[count];
    for (int i = 0; i < count; ++i) {
        ar[i] = 3 * i;
    }
    return ar;
}automatic
dynamic
thread
static
{
    int* number = new int(5);
    if (!(number = nullptr)) // typo, leak
        f(number);
    delete number; // noop
}{
    int* number = new int(5);
} // forgot to delete, leak{
    int* number = new int(5);
    int* ar = new int[100'000'000]; // leak if throws
    delete[] ar;
    delete number;
}automatic
dynamic
thread
static
{
    std::unique_ptr<int> number = std::make_unique<int>(5);
    if (!(number = nullptr)) // typo, no leak
        f(number);
}{
    auto number = std::make_unique<int>(5);
} //  automatically deleted, no leak{
    auto number = std::make_unique<int>(5);
    auto ar = std::make_unique<int[]>(100'000'000);
    // no leak if throws
}{
    std::string s;
    // storage allocated on stack
    // std::string constructor invoked
    //    internal string buffer allocated
    //    size set to 0
}
// storage deallocated on stack
// std::string destructor invoked
//    internal string buffer deallocatedTo be continued...
Part I