# 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