# C++ Advanced Patterns

## Template Metaprogramming

Variadic Templates:
```cpp
template<typename... Args>
auto sum(Args... args) {
    return (args + ...);  // Fold expression
}

template<typename... Args>
void print_all(Args&&... args) {
    ((std::cout << std::forward<Args>(args) << " "), ...);
}
```

SFINAE and if constexpr:
```cpp
template<typename T>
auto to_string(const T& value) -> std::string {
    if constexpr (std::is_arithmetic_v<T>) {
        return std::to_string(value);
    } else if constexpr (requires { value.to_string(); }) {
        return value.to_string();
    } else {
        return "unknown";
    }
}
```

## Testing with Google Test

Complete Test Suite:
```cpp
#include <gtest/gtest.h>

class CalculatorTest : public ::testing::Test {
protected:
    Calculator calc;

    void SetUp() override {
        calc = Calculator{};
    }
};

TEST_F(CalculatorTest, Addition) {
    EXPECT_EQ(calc.add(2, 3), 5);
}

TEST_F(CalculatorTest, DivisionByZero) {
    EXPECT_THROW(calc.divide(1, 0), std::invalid_argument);
}

// Parameterized test
class AdditionTest : public ::testing::TestWithParam<std::tuple<int, int, int>> {};

TEST_P(AdditionTest, Works) {
    auto [a, b, expected] = GetParam();
    EXPECT_EQ(Calculator{}.add(a, b), expected);
}

INSTANTIATE_TEST_SUITE_P(Basics, AdditionTest,
    ::testing::Values(
        std::make_tuple(1, 1, 2),
        std::make_tuple(0, 0, 0),
        std::make_tuple(-1, 1, 0)
    ));
```

## Catch2 Testing Framework

Alternative Testing:
```cpp
#include <catch2/catch_test_macros.hpp>

TEST_CASE("Vector operations", "[vector]") {
    std::vector<int> v;

    SECTION("starts empty") {
        REQUIRE(v.empty());
    }

    SECTION("can add elements") {
        v.push_back(1);
        REQUIRE(v.size() == 1);
        REQUIRE(v[0] == 1);
    }

    SECTION("can be resized") {
        v.resize(10);
        REQUIRE(v.size() == 10);
    }
}

TEST_CASE("Generators", "[generator]") {
    auto i = GENERATE(range(1, 10));
    REQUIRE(i > 0);
    REQUIRE(i < 10);
}
```

## Advanced Concurrency

Thread Pool Implementation:
```cpp
#include <thread>
#include <queue>
#include <functional>
#include <future>
#include <condition_variable>

class ThreadPool {
public:
    explicit ThreadPool(size_t num_threads) : stop_(false) {
        for (size_t i = 0; i < num_threads; ++i) {
            workers_.emplace_back([this] {
                while (true) {
                    std::function<void()> task;
                    {
                        std::unique_lock lock(mutex_);
                        cv_.wait(lock, [this] { return stop_ || !tasks_.empty(); });
                        if (stop_ && tasks_.empty()) return;
                        task = std::move(tasks_.front());
                        tasks_.pop();
                    }
                    task();
                }
            });
        }
    }

    template<typename F, typename... Args>
    auto enqueue(F&& f, Args&&... args) -> std::future<std::invoke_result_t<F, Args...>> {
        using return_type = std::invoke_result_t<F, Args...>;
        auto task = std::make_shared<std::packaged_task<return_type()>>(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...));
        auto result = task->get_future();
        {
            std::unique_lock lock(mutex_);
            tasks_.emplace([task] { (*task)(); });
        }
        cv_.notify_one();
        return result;
    }

    ~ThreadPool() {
        {
            std::unique_lock lock(mutex_);
            stop_ = true;
        }
        cv_.notify_all();
        for (auto& worker : workers_) {
            worker.join();
        }
    }

private:
    std::vector<std::thread> workers_;
    std::queue<std::function<void()>> tasks_;
    std::mutex mutex_;
    std::condition_variable cv_;
    bool stop_;
};
```

Lock-Free Queue:
```cpp
#include <atomic>
#include <optional>

template<typename T>
class LockFreeQueue {
    struct Node {
        std::optional<T> data;
        std::atomic<Node*> next;
    };

    std::atomic<Node*> head_;
    std::atomic<Node*> tail_;

public:
    LockFreeQueue() {
        auto* dummy = new Node{std::nullopt, nullptr};
        head_.store(dummy);
        tail_.store(dummy);
    }

    void push(T value) {
        auto* new_node = new Node{std::move(value), nullptr};
        Node* old_tail;
        while (true) {
            old_tail = tail_.load();
            Node* null_node = nullptr;
            if (old_tail->next.compare_exchange_weak(null_node, new_node)) {
                break;
            }
            tail_.compare_exchange_weak(old_tail, old_tail->next);
        }
        tail_.compare_exchange_weak(old_tail, new_node);
    }

    auto pop() -> std::optional<T> {
        Node* old_head;
        while (true) {
            old_head = head_.load();
            Node* old_tail = tail_.load();
            Node* next = old_head->next.load();
            if (old_head == old_tail) {
                if (next == nullptr) return std::nullopt;
                tail_.compare_exchange_weak(old_tail, next);
            } else {
                if (head_.compare_exchange_weak(old_head, next)) {
                    auto result = std::move(next->data);
                    delete old_head;
                    return result;
                }
            }
        }
    }
};
```

## Memory Management Patterns

Custom Allocator:
```cpp
template<typename T>
class PoolAllocator {
    struct Block {
        Block* next;
    };

    Block* free_list_ = nullptr;
    std::vector<std::unique_ptr<std::byte[]>> pools_;
    size_t block_size_ = std::max(sizeof(T), sizeof(Block));
    size_t pool_size_ = 1024;

public:
    using value_type = T;

    auto allocate(size_t n) -> T* {
        if (n != 1) throw std::bad_alloc();
        if (!free_list_) allocate_pool();
        Block* block = free_list_;
        free_list_ = block->next;
        return reinterpret_cast<T*>(block);
    }

    void deallocate(T* p, size_t) {
        Block* block = reinterpret_cast<Block*>(p);
        block->next = free_list_;
        free_list_ = block;
    }

private:
    void allocate_pool() {
        auto pool = std::make_unique<std::byte[]>(block_size_ * pool_size_);
        for (size_t i = 0; i < pool_size_; ++i) {
            Block* block = reinterpret_cast<Block*>(pool.get() + i * block_size_);
            block->next = free_list_;
            free_list_ = block;
        }
        pools_.push_back(std::move(pool));
    }
};
```

## Production Patterns

Dependency Injection:
```cpp
// Interface
class ILogger {
public:
    virtual ~ILogger() = default;
    virtual void log(std::string_view message) = 0;
};

// Implementation
class ConsoleLogger : public ILogger {
public:
    void log(std::string_view message) override {
        std::println("{}", message);
    }
};

// Service using dependency injection
class UserService {
    std::shared_ptr<ILogger> logger_;

public:
    explicit UserService(std::shared_ptr<ILogger> logger)
        : logger_(std::move(logger)) {}

    void create_user(std::string_view name) {
        logger_->log(std::format("Creating user: {}", name));
        // Business logic
    }
};

// Factory
class ServiceFactory {
public:
    static auto create_user_service() -> std::unique_ptr<UserService> {
        return std::make_unique<UserService>(
            std::make_shared<ConsoleLogger>()
        );
    }
};
```

## Build System Patterns

Conan 2.0 Integration:
```python
# conanfile.py
from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout

class MyProjectConan(ConanFile):
    name = "myproject"
    version = "1.0.0"
    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeToolchain", "CMakeDeps"
    requires = "fmt/10.2.1", "nlohmann_json/3.11.3"
    tool_requires = "gtest/1.14.0"

    def layout(self):
        cmake_layout(self)

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()
```

vcpkg Manifest:
```json
{
    "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
    "name": "myproject",
    "version": "1.0.0",
    "dependencies": [
        "fmt",
        "nlohmann-json",
        "spdlog",
        { "name": "gtest", "features": [ "gmock" ] }
    ]
}
```

## Performance Optimization

Cache-Friendly Data Structures:
```cpp
// Structure of Arrays (SoA) for better cache performance
struct Particles {
    std::vector<float> x;
    std::vector<float> y;
    std::vector<float> z;
    std::vector<float> vx;
    std::vector<float> vy;
    std::vector<float> vz;

    void update(float dt) {
        // Process all x values together (cache-friendly)
        for (size_t i = 0; i < x.size(); ++i) {
            x[i] += vx[i] * dt;
        }
        // Then y values
        for (size_t i = 0; i < y.size(); ++i) {
            y[i] += vy[i] * dt;
        }
        // Then z values
        for (size_t i = 0; i < z.size(); ++i) {
            z[i] += vz[i] * dt;
        }
    }
};
```

SIMD Optimization:
```cpp
#include <immintrin.h>

void add_vectors_simd(float* a, float* b, float* result, size_t n) {
    size_t i = 0;
    // Process 8 floats at a time using AVX
    for (; i + 7 < n; i += 8) {
        __m256 va = _mm256_loadu_ps(a + i);
        __m256 vb = _mm256_loadu_ps(b + i);
        __m256 vr = _mm256_add_ps(va, vb);
        _mm256_storeu_ps(result + i, vr);
    }
    // Handle remaining elements
    for (; i < n; ++i) {
        result[i] = a[i] + b[i];
    }
}
```
