Advanced C++ Projects

Master complex programming concepts and design patterns

🎯 Advanced C++ Projects

Tackle sophisticated programming challenges using advanced C++ features like templates, STL, multithreading, and design patterns. These projects prepare you for professional software development with complex architectures and performance optimization.


#include <iostream>
#include <memory>
#include <thread>
#include <mutex>

template<typename T>
class ThreadSafeQueue {
private:
    std::queue<T> queue_;
    std::mutex mutex_;
public:
    void push(T item) {
        std::lock_guard<std::mutex> lock(mutex_);
        queue_.push(item);
    }
};
                                    

Advanced Project Categories

🧠

Design Patterns

Professional software architecture

Singleton Pattern Observer Pattern Factory Pattern

Multithreading

Concurrent programming projects

Thread Pool Producer-Consumer Parallel Algorithms
🔧

Template Programming

Generic programming solutions

Custom Containers Meta Programming SFINAE Techniques
🌐

Network Programming

Client-server applications

TCP Server HTTP Client Chat Application

🔹 Thread Pool Implementation

A scalable thread pool for concurrent task execution:

#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>

class ThreadPool {
private:
    std::vector<std::thread> workers;
    std::queue<std::function<void()>> tasks;
    std::mutex queue_mutex;
    std::condition_variable condition;
    bool stop;

public:
    ThreadPool(size_t threads) : stop(false) {
        for(size_t i = 0; i < threads; ++i) {
            workers.emplace_back([this] {
                for(;;) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(this->queue_mutex);
                        this->condition.wait(lock, [this]{ return this->stop || !this->tasks.empty(); });
                        
                        if(this->stop && this->tasks.empty())
                            return;
                            
                        task = std::move(this->tasks.front());
                        this->tasks.pop();
                    }
                    task();
                }
            });
        }
    }

    template<class F, class... Args>
    auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
        using return_type = typename std::result_of<F(Args...)>::type;

        auto task = std::make_shared<std::packaged_task<return_type()>>(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)
        );

        std::future<return_type> res = task->get_future();
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            if(stop)
                throw std::runtime_error("enqueue on stopped ThreadPool");

            tasks.emplace([task](){ (*task)(); });
        }
        condition.notify_one();
        return res;
    }

    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            stop = true;
        }
        condition.notify_all();
        for(std::thread &worker: workers)
            worker.join();
    }
};

// Usage example
int main() {
    ThreadPool pool(4);
    std::vector<std::future<int>> results;

    for(int i = 0; i < 8; ++i) {
        results.emplace_back(
            pool.enqueue([i] {
                std::cout << "Task " << i << " running on thread " 
                         << std::this_thread::get_id() << std::endl;
                std::this_thread::sleep_for(std::chrono::seconds(1));
                return i * i;
            })
        );
    }

    for(auto && result : results)
        std::cout << "Result: " << result.get() << std::endl;

    return 0;
}

🔹 Smart Pointer Implementation

Custom smart pointer with reference counting:

#include <iostream>
using namespace std;

template<typename T>
class SmartPtr {
private:
    T* ptr;
    int* ref_count;

public:
    // Constructor
    explicit SmartPtr(T* p = nullptr) : ptr(p) {
        ref_count = new int(1);
        cout << "SmartPtr created. Ref count: " << *ref_count << endl;
    }

    // Copy constructor
    SmartPtr(const SmartPtr<T>& sp) : ptr(sp.ptr), ref_count(sp.ref_count) {
        (*ref_count)++;
        cout << "SmartPtr copied. Ref count: " << *ref_count << endl;
    }

    // Assignment operator
    SmartPtr<T>& operator=(const SmartPtr<T>& sp) {
        if (this != &sp) {
            // Decrease current reference count
            (*ref_count)--;
            if (*ref_count == 0) {
                delete ptr;
                delete ref_count;
            }

            // Copy new values
            ptr = sp.ptr;
            ref_count = sp.ref_count;
            (*ref_count)++;
        }
        return *this;
    }

    // Destructor
    ~SmartPtr() {
        (*ref_count)--;
        cout << "SmartPtr destroyed. Ref count: " << *ref_count << endl;
        if (*ref_count == 0) {
            delete ptr;
            delete ref_count;
            cout << "Object deleted" << endl;
        }
    }

    // Overload * operator
    T& operator*() {
        return *ptr;
    }

    // Overload -> operator
    T* operator->() {
        return ptr;
    }

    // Get reference count
    int getCount() {
        return *ref_count;
    }
};

class TestClass {
public:
    int value;
    TestClass(int v) : value(v) {
        cout << "TestClass created with value: " << value << endl;
    }
    ~TestClass() {
        cout << "TestClass destroyed with value: " << value << endl;
    }
};

int main() {
    SmartPtr<TestClass> sp1(new TestClass(10));
    cout << "Value: " << sp1->value << endl;
    
    {
        SmartPtr<TestClass> sp2 = sp1;
        cout << "Reference count: " << sp2.getCount() << endl;
    } // sp2 goes out of scope
    
    cout << "Reference count after sp2 destroyed: " << sp1.getCount() << endl;
    
    return 0;
}

🔹 Observer Pattern Implementation

Event-driven programming with observer pattern:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

// Observer interface
class Observer {
public:
    virtual ~Observer() {}
    virtual void update(const string& message) = 0;
};

// Subject interface
class Subject {
private:
    vector<Observer*> observers;
    
public:
    virtual ~Subject() {}
    
    void attach(Observer* observer) {
        observers.push_back(observer);
    }
    
    void detach(Observer* observer) {
        observers.erase(remove(observers.begin(), observers.end(), observer), observers.end());
    }
    
    void notify(const string& message) {
        for(Observer* observer : observers) {
            observer->update(message);
        }
    }
};

// Concrete Subject
class NewsAgency : public Subject {
private:
    string news;
    
public:
    void setNews(const string& newNews) {
        news = newNews;
        notify(news);
    }
    
    string getNews() const {
        return news;
    }
};

// Concrete Observer
class NewsChannel : public Observer {
private:
    string name;
    
public:
    NewsChannel(const string& channelName) : name(channelName) {}
    
    void update(const string& message) override {
        cout << name << " received news: " << message << endl;
    }
};

int main() {
    NewsAgency agency;
    
    NewsChannel cnn("CNN");
    NewsChannel bbc("BBC");
    NewsChannel fox("Fox News");
    
    agency.attach(&cnn);
    agency.attach(&bbc);
    agency.attach(&fox);
    
    agency.setNews("Breaking: C++ 23 Standard Released!");
    
    cout << "\nDetaching BBC...\n" << endl;
    agency.detach(&bbc);
    
    agency.setNews("Update: New C++ Features Announced!");
    
    return 0;
}

🧠 Test Your Knowledge

Which C++ feature allows you to write generic code that works with different data types?