C++ 工具函数库

这篇博客介绍了一个名为`Utils`的C++工具库,包含随机数生成、计时器、输出函数、常量定义以及信号槽功能。其中,`Random`类提供了快速的随机数生成方法,`Timer`类用于方便地计算代码执行时间,而`Signal`模板类实现了信号和槽的机制,便于事件驱动编程。此外,还提供了一组便利的打印函数,支持多种类型的数据输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在写一些大型项目的过程中经常需要一些工具函数,例如获取随机数、计时器、打印函数、重要常量(如最大值)、信号与槽等,由于每一个工程都自己手动实现一个实在是太傻,我将其总结放入一个文件中。


utils.h

// Copyright(C), Edward-Elric233
// Author: Edward-Elric233
// Version: 1.0
// Date: 2022/6/27
// Description: 
#ifndef UTILS_H
#define UTILS_H

#include "json.hpp"
#include <iostream>
#include <random>
#include <chrono>
#include <fstream>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <functional>

namespace edward {

constexpr int INF = 0x3f3f3f3f;

//extern std::ofstream ofs;

inline void print() {
    std::cout << "\n";
//    ofs << "\n";
}
template<typename T, typename... Args>
void print(T&& first, Args&&... args) {
    std::cout << first << " ";
//    ofs << first << " ";
    print(std::forward<Args>(args)...);
}

template<typename Iter>
void printArr(Iter begin, Iter end) {
    while (begin != end) {
        std::cout << *begin++ << " ";
    }
    std::cout << "\n";
}

template<typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& pr) {
    os << pr.first << " " << pr.second;
    return os;
}

template<typename Container>
void printArr(const Container& container) {
    for (auto x : container) {
        std::cout << x << " ";
    }
    std::cout << "\n";
}

class Random {
public:
    // random number generator.
    static std::mt19937 pseudoRandNumGen;
    static void initRand(int seed) { pseudoRandNumGen = std::mt19937(seed); }   //设置随机数种子
    static int fastRand(int lb, int ub) { return (pseudoRandNumGen() % (ub - lb)) + lb; }
    static int fastRand(int ub) { return pseudoRandNumGen() % ub; }
    static int rand(int lb, int ub) { return std::uniform_int_distribution<int>(lb, ub - 1)(pseudoRandNumGen); }
    static int rand(int ub) { return std::uniform_int_distribution<int>(0, ub - 1)(pseudoRandNumGen); }
};

class Timer {
    std::chrono::time_point<std::chrono::system_clock> timePoint_;
public:
    Timer(): timePoint_(std::chrono::system_clock::now()) {}
    Timer(const Timer&) = delete;
    ~Timer() = default;
    void operator() (const std::string& msg) {
        auto duration = std::chrono::system_clock::now() - timePoint_;
        print(msg, static_cast<double>(duration.count()) / decltype(duration)::period::den, "s");
    }
    void reset() {
        timePoint_ = std::chrono::system_clock::now();
    }
    void operator() (nlohmann::json& arr) {
        auto duration = std::chrono::system_clock::now() - timePoint_;
        arr.push_back(duration.count());
    }

};



using Slot = std::shared_ptr<void>;

//前置声明
template<typename Signature>
class Signal;
template<typename Ret, typename... Args>
class Signal<Ret(Args...)>;

namespace detail {
    //前置声明
    template<typename Callback> class SlotImpl;

    template<typename Callback>
    class SignalImpl {
    public:
        using SlotList = std::unordered_map<SlotImpl<Callback> *, std::weak_ptr<SlotImpl<Callback>>>;

        SignalImpl()
        : slots_(new SlotList)
        , mutex_() {

        }
        ~SignalImpl() {

        }

        //只能在加锁后使用
        void cowWithLock() {
            if (!slots_.unique()) {
                slots_.reset(new SlotList(*slots_));
            }
        }

        //添加槽函数
        void add(const std::shared_ptr<SlotImpl<Callback>> &slot) {
            std::lock_guard<std::mutex> lockGuard(mutex_);
            cowWithLock();
            slots_->insert({slot.get(), slot});
        }
        //供SlotImpl调用,删除槽函数
        void remove(SlotImpl<Callback> *slot) {
            std::lock_guard<std::mutex> lockGuard(mutex_);
            cowWithLock();
            slots_->erase(slot);
        }

        std::shared_ptr<SlotList> getSlotList() {
            std::lock_guard<std::mutex> lockGuard(mutex_);
            return slots_;
        }
    private:
        std::mutex mutex_;
        //保存SlotImpl的weak_ptr
        //之所以不保存SlotList而是保存其shared_ptr是为了实现COW
        std::shared_ptr<SlotList> slots_;
    };

    template<typename Callback>
    class SlotImpl {
    public:
        SlotImpl(Callback&& cb, const std::shared_ptr<SignalImpl<Callback>> &signal)
        : cb_(cb)
        , signal_(signal) {

        }
        ~SlotImpl() {
            auto signal = signal_.lock();
            if (signal) {
                signal->remove(this);
            }
        }

        Callback cb_;
    private:
        //保存SignalImpl的weak_ptr
        std::weak_ptr<SignalImpl<Callback>> signal_;
    };
}

template<typename Ret, typename... Args>
class Signal<Ret(Args...)> {
public:
    using Callback = std::function<Ret(Args...)>;
    using SignalImpl = detail::SignalImpl<Callback>;
    using SlotImpl = detail::SlotImpl<Callback>;

    Signal()
    : impl_(new SignalImpl) {

    }

    ~Signal() {

    }

    /*!
     * 添加槽函数
     * @param cb 槽函数
     * @return 需要保存这个智能指针,否则会自动从槽函数列表中删除
     */
    template<typename Func>
    Slot connect(Func&& cb) {
        std::shared_ptr<SlotImpl> slot(new SlotImpl(std::forward<Func>(cb), impl_));
        impl_->add(slot);
        return slot;
    }

    template<typename ...ARGS>
    void operator() (ARGS&&... args) {
        auto slots = impl_->getSlotList();
        //使用引用避免智能指针的解引用
        auto &s = *slots;
        for (auto &&[pSlotImpl, pWkSlotImpl] : s) {
            auto pShrSlotImpl = pWkSlotImpl.lock();
            if (pShrSlotImpl) {
                pShrSlotImpl->cb_(std::forward<ARGS>(args)...);
            }
        }
    }

private:
    //保存shared_ptr的原因是需要传递给SlotImpl,在SlotImpl析构的时候会清除自己
    const std::shared_ptr<SignalImpl> impl_;
};



}

#endif //UTILS_H

utils.cpp

// Copyright(C), Edward-Elric233
// Author: Edward-Elric233
// Version: 1.0
// Date: 2022/6/27
// Description: 
#include "utils.h"

namespace edward {

std::mt19937 Random::pseudoRandNumGen(std::chrono::system_clock::now().time_since_epoch().count()); //默认使用当下时间戳初始化随机数种子,精确到纳秒

//std::ofstream ofs("../test/debug.txt");

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值