# atom.utils **Repository Path**: shucharjer/atom.utils ## Basic Information - **Project Name**: atom.utils - **Description**: No description available - **Primary Language**: C++ - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2025-02-25 - **Last Updated**: 2025-06-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # atom.utils [English](readme.md) | 简体中文 atom.utils是atom引擎中所使用到的一系列基础工具的集合,它是一个headers-only的现代C++库,以便于在各种项目中链接。现在它包括一些数据结构(比如sparse_map、compressed_pair、spin_lock等)以及反射和它对应的序列化。 这个库的宗旨是提供易用的现代C++基础工具,帮助用户快速在现代C++中构建内容。 ## 快速开始 ### 编译器要求 这个库只支持C++20或者更高版本,所以确保你的编译器支持C++20. - g++ 10 above; - clang++13 above; - msvc 14.29 above. ### 安装与编译 #### 手动安装 1. 克隆这个仓库 ```shell git clone https://github.com/Shucahrjer/atom.utils cd atom.utils ``` 2. 构建 ```shell cmake -B build # or you could add other args, such as cmake -DCMAKE_C_COMPILER="clang" -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_MAKE_PROGRAM="ninja" -G "Ninja" -B build cd build cmake --build . --config debug ``` 3. 安装 ```shell cmake --install . # --prefix ``` 4. 开始开发 ## 简介 接下来的内容是基于这样一条语句的 ```c++ using namespace atom::utils; ``` ### 目录
核心
    多态
    
    管道与闭包
        适配器闭包
        闭包
范围
反射
    无宏反射
    自定义反射
    序列化支持
结构
    dense_map
    dense_set
线程
    线程池
    协程
    自旋锁
    混合锁
信号
    lambda
    委托
    
    调度器
内存
    内存池
    分配器
    销毁器
    存储
    around_ptr
### 核心 #### 多态 提供了对动态多态的静态封装,在此之前,请包含 `core/poly.hpp` 对于这种多态的封装,需要让该类型继承自 `invoke_list`,并提供 `interface`模板和 `implementation`模板 ```c++ struct basic_object : invoke_list { template struct interface : Base { void foo() const { return poly_call<0>(*this); } void foo2() { return poly_call<1>(*this); } void foo3(int i) { return poly_call<2>(*this, i); } }; template using implementation = value_list<&Impl::foo, &Impl::foo2, &Impl::foo3>; }; ``` 使用示例 ```c++ struct basic_impl { void foo() const { println("called foo() in basic_impl"); } void foo2() { println("called foo2() in basic_impl"); } void foo3(int i) { println(std::format("called foo3() in basic_impl, i: {}", i)); } }; poly basic_poly = basic_impl{}; // 支持以指针的方式进行调用 poly->foo(); poly->foo2(); poly->foo3(/* a int value*/); ``` 它也支持再次继承,并仅重写其中的部分逻辑 ```c++ // 继承basic_object的调用列表 struct advanced_object : append_invoke_list_t())), void()> { // 继承basic_object::interface template struct interface : basic_object::interface { // 需要新提供的函数 void foo4() { return poly_call<3>(*this); } }; // 往basic_object::implementation后添加成员函数指针 template using implementation = append_value_list_t, &Impl::foo4>; }; struct advanced_impl : basic_impl { void foo2() { println("called foo2() in advanced_impl"); } void foo4() { println(std::format("called foo4() in avanced_impl")); } }; ``` ```c++ poly advanced_poly = advanced_impl{}; println("advanced_impl:"); advanced_poly->foo(); advanced_poly->foo2(); advanced_poly->foo4(); ``` #### 对 提供了压缩对、逆转的压缩对、逆转的对,并且它们都支持结构化绑定 ```c++ struct empty {}; compressed_pair cpair; empty& e = cpair.first(); auto& rcpair reverse(cpair); e = rcpair.second(); const auto& [f, s] = cpair; const auto& [rf, rs] = rcpair; std::pair pair; auto& rpair = reverse(pair); ``` #### 管道与闭包 ##### 适配器闭包 由于C++20并没有C++23中的范围适配器闭包,因此不得不在C++20引入一系列类型并对其进行支持 顾名思义,`pipeline_base`是范围闭包需要继承的基类,`pipline_result`是管道运算后的结果,`closure`就是闭包 你可以通过 `pipeline_base`快速构建一个范围闭包,可以参考以下示例 ```c++ struct empty_fn { using pipeline_tag = pipeline_tag; template requires std::is_default_constructible_v constexpr auto operator()(Rng&& range) const { return Rng{}; } }; constexpr inline empty_fn empty; ... // 范围与构建的范围闭包进行管道操作 std::vector vector = { 2, 3, 4, 6 }; auto empty_vector = vector | empty; assert(empty_vector.empty()); // 范围闭包与其它闭包类型进行管道操作 auto closure = empty | std::views::reverse; // 范围与上述产生的结果进行管道操作 auto another_empty_vector = vector | closure; assert(another_empty_vector.empty()); ``` 需要指出的是,它不仅仅是范围适配器闭包,它是真的适配器闭包。 这意味着你可以将对其它类型进行管道操作符,只要提供了合适的 `operator()`。 ##### 闭包 除了范围适配器闭包外,还提供了一种特殊的闭包,通过它,我们能快速实现惰性构造 ```c++ struct get_vector_fn { template std::vector operator()(Args&&... args) { return std::vector(std::forward(args)...); } }; std::vector origin = { 2, 2, 3, 34, 2, 523, 53, 5, 346, 54, 645, 7, 4567, 56, 75 }; auto end = origin.cend(); auto closure = make_closure(end); auto vec = closure(origin.cbegin() + 2); auto vec2 = (origin.cbegin() + 2) | closure; // 3, 34, 2, 523, 53, 5, 346, 54, 645, 7, 4567, 56, 75 ``` ### 范围 众所周知,C++23中所提供的std::ranges::to是一个非常好用的函数,它能用简单的语法从一种类型的范围构建另一种类型的容器。 现在,它被带到了C++20,如果使用C++23,那么会调用标准库中的实现。 ```c++ auto map = std::map{{1, 2}, {2, 1}, {465, 0}, {53, 634}}; auto values = map | std::views::values; auto vector = ranges::to(values); ``` 它几乎是标准库中的实现,除了C++20没有C++23中的std::from_range。 不难推测,它也能像C++23中一样获得一个闭包。 ```c++ auto closure = ranges::to>(4); auto vector = closure(values); ``` 在实现std::ranges::to的过程中,也引入了一些类型, 比如 `phony_input_iterator`、`pipline_result`和 `range_closure`, 它们分别是用于延迟加载的“假输入迭代器”,管道运算的结果和用于延迟加载的闭包。 可以尝试使用它们来实现一些标准库之外的延迟加载。 ### 反射 ```c++ #include // 仅需包含单个头文件 ``` #### 无宏反射 这一部分仅支持聚合类型。 ```c++ // definition struct a { int m1; char m2; }; ``` ##### 类型名 ```c++ auto name = name_of(); ``` ##### 成员数量 ```c++ auto count = member_count_v(); // consteval // auto count = member_count_of(); ``` ##### 成员名 ```c++ auto names = member_names_of(); ``` ##### 获取成员 ```c++ a inst {}; auto& m1 = get<0>(inst); auto& m2 = get<"m2">(inst); ``` ##### 成员偏移(成员指针) ```c++ a inst {}; auto& offsets = offsets_of(); inst.*(std::get<0>(offsets)) = 114514; inst.*(std::get<1>(offsets)) = 'b'; ``` #### 自定义反射 ```c++ class b { int m1; std::vector m2; void print() { std::ranges::for_each(m2, [](const auto v) { std::cout << v << ' '; }); } public: REFL_MEMBERS(b, m1, m2) REFL_MEMBERS(b, print) }; ``` 其余用法与之前一样。 在使用MSVC时,尽管宏所展开的内容是正常的,但可能需要将宏内联展开! #### 序列化支持 也支持了 `nlohmann-json`的序列化与反序列化 ```c++ // 序列化 nlohmann::json json = inst; std::cout << json.dump(4) << '\n'; // 更改member1的值,期待它在反序列化之后变回之前的值 inst.m1 = 90; // 反序列化 inst = json; std::cout << inst.m1 << '\n'; ``` ### 线程 #### 线程池 #### 协程 #### 自旋锁 #### 混合锁 ### 结构 #### dense_map #### dense_set ### 信号 #### lambda 带有捕获列表的lambda表达式无法隐式转换为指针。 现在,我们能通过一个函数快速获取到指针。 ```c++ auto lambda = [&](){}; auto ptr = make_function_ptr(); // void(*ptr)() = make_function_ptr(); ``` #### 委托 ```c++ delegate d; d.bind(); // 或者一步到位 delegate d2 { spread_arg }; ``` #### 槽 #### 调度器 ### 内存 提供了分配器、内存池和存储器 #### 内存池 提供了两种类型的内存池 ```c++ synchronized_pool synchronized_pool{}; unsynchronized_pool unsynchronized_pool{}; ``` #### 分配器 提供了两种类型的分配器:`standard_allocator`和 `allocator` 其中,`standard_allocator`只是将 `std::allocator`封装了一下 而 `allocator`则需要从内存池创建 ```c++ synchronized_pool pool; allocator allocator{pool}; std::vector vector{allocator}; ``` #### 销毁器 #### 存储 提供了独占式的存储器和共享式的存储器。 共享式存储器支持写时复制,适合用在复制开销较大的场景 需要注意的是,这种写时复制只在使用 `=`时生效 #### around_ptr