简介
Modern STL (简称: MSTL) 是我们基于concept
等 C++20 的新特性构建的 C++ 模板库, 致力于以更现代化的方法实现STL提供的功能.
MSTL 提供函数式风格的迭代器,
与STL相似的模板容器(Array
, Vector
, LinkedList
等),
表示可能为空的值的Option
,
用于取代异常机制的 Result
,
以及含编码的字符和字符串 (AsciiChar
, AsciiString
, UTF8Char
, UTF8String
) 等功能.
MSTL的主旨在于现代化与零成本抽象, 致力于以零成本, 现代化的方式完成STL能完成的工作.
项目地址: https://github.com/a1393323447/modern_stl
项目目前在github上以GPLv3开源, 欢迎感兴趣的朋友关注, 使用, 学习, 交流以及参与改进.
示例
迭代器的使用
MSTL实现了函数式风格的迭代器, 在进一步简化代码的同时实现了零成本抽象.
#include <mstl/mstl.h>
#include <cassert>
using namespace mstl;
using mstl::collection::Array;
using mstl::collection::Vector;
using namespace mstl::iter;
template<typename T>
struct Pow {
T pow;
bool operator==(const Pow &rhs) const {
return pow == rhs.pow;
}
};
int main() {
Array<i32, 10> arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 管道风格
auto pow_arr1 =
arr.iter() // 获取arr的迭代器
| map([](const auto& ele) { // 把迭代器中的元素转化为它的平方
return ele * ele;
})
| map([](const auto& ele) { // 把迭代器中的元素转化为Pow<usize>对象
return Pow<usize>{
static_cast<usize>(ele * ele)
};
})
| filter([](const auto& ele) { // 滤去pow成员为奇数的元素
return ele.pow % 2 == 0;
})
| collect<Vector<Pow<usize>>>(); // 把元素收集到Vector<Pow<usize>>中
// 链式风格
auto pow_arr2 = combine(arr.iter(), // 获取arr的迭代器
Map{}, [](auto ele) { // 把迭代器中的元素转化为它的平方
return ele * ele;
},
Map{}, [](auto ele) { // 把迭代器中的元素转化为Pow<usize>对象
return Pow<usize>{ static_cast<usize>(ele * ele) };
},
Filter{}, [](auto& ele) { // 滤去pow成员为奇数的元素
return ele.pow % 2 == 0;
},
CollectAs<Vector<Pow<usize>>>{} // 把元素收集到Vector<Pow<usize>>中
);
auto pow_arr3 = Vector<Pow<usize>>{
Pow<usize>{16},
Pow<usize>{256},
Pow<usize>{1296},
Pow<usize>{4096},
Pow<usize>{10000},
};
assert(pow_arr1 == pow_arr2);
assert(pow_arr2 == pow_arr3);
}
编译时类型运算
MSTL实现了用于编译时类型运算的TypeList
类, 可以对类型进行提取, 应用, 过滤, 转化等操作.
#include <mstl/mstl.h>
using namespace mstl::utility;
int main() {
constexpr auto tuple = make_tuple(1, 2.0, 3l);
constexpr auto ls1 = extract_from(tuple); // 从类模板中提取模板参数
static_assert(ls1 == TypeList<int, double, long>);
constexpr auto ls2 = TypeList<int, double>;
constexpr auto t1 = ls2 | apply_to<Tuple>(); // 把类型列表应用到类模板中
static_assert(t1 == TypeConstInstance<Tuple<int, double>>);
constexpr auto ls3 = ls2 | append<char, float>(); // 在类型列表后添加元素
static_assert(ls3 == TypeList<int, double, char, float>);
constexpr auto ls4 = ls3 | prepend<double*, const char*>(); // 在类型列表前添加元素
static_assert(ls4 == TypeList<double*, const char*, int, double, char, float>);
static_assert(ls4.at<1>() == TypeConstInstance<const char*>); // 按索引取出元素
constexpr auto ls5 = ls4
| filter([]<typename T>(TypeConst<T>) { // 过滤类型元素, 如同普通元素那样
return_v<(sizeof(T) < 8)>; // 使用return_v返回一个编译期常量值. 此处返回bool类型, 滤去size小于8的类型
})
| map([]<typename T>(TypeConst<T>) { // 转换类型元素, 如同普通元素那样.
return_t<T*>; // 使用return_t返回一个类型. 此处使列表中的每个元素T转换成T*.
});
static_assert(ls5 == TypeList<int*, char*, float*>);
}
按值匹配 (match
)
MSTL实现了按值匹配功能, 不妨看作可以返回值且能匹配数值范围的switch-case
语句.
#include <mstl/mstl.h>
using namespace mstl;
using namespace mstl::utility;
int main() {
constexpr i32 i = 10;
// 支持链式调用风格
constexpr auto x = match(i)
.when(10, []{return 10;}) // 匹配成功, 表达式返回10
.rest([]{return 20;})
.finale(); // 获取返回值
static_assert(x == 10);
constexpr auto y = match(i)
.when(1, [](){return 5;}) // 失配
.when(ops::Range(2, 10), [](){return 10;}) // 失配
.rest([](){return 20;}) // 匹配剩余值, 匹配成功, 表达式返回20
.finale();
static_assert(y == 20);
// 也支持管道风格
constexpr auto z = match(i)
| when(1, [](){return 5;}) // 失配
| when(ops::Range(2, 11), [](){return 10;}) // 匹配成功, 表达式返回10
| rest([](){return 20;})
| finale();
static_assert(z == 10);
}
使用字符串
MSTL 实现了含编码的字符串, 且对字符串字面量支持编译期无效字符检查.
更多示例参见此处的单元测试.
开始使用
MSTL是纯头文件库, 使用CMake
进行管理进行构建.
因此, 我们建议您在使用本库时, 也尝试使用CMake
构建您的项目.
需求
包 | 版本 | 备注 |
CMake | >=3.14 | 若您使用CMake 构建本项目和您的其他项目 |
GCC | >= 12.2.0 | 暂不支持 MSVC |
Boost (可选) | >= 1.77.0 | 用于构建单元测试 |
Google Benchmark (可选) | >= 1.7.0 | 用于构建Benchmarks |
准备工作
Clone仓库, 并Checkout main
分支.
git clone https://github.com/a1393323447/modern_stl.git
cd modern_stl
git checkout main
构建与使用(通过CMake
)
进入项目目录, 使用CMake
构建并安装项目
# 假设您处于modern_stl目录下
md build
cd build
cmake .. # 若您使用Windows操作系统, 还应该添加 -G "Unix Makefiles". MSTL还不支持MSVC
# 若您需要指定安装路径, 还应该添加 -DCMAKE_INSTALL_PREFIX:PATH=...
cmake --build . --config Release --target install
然后您便可以在新的项目中使用mstl
. 您需要在CMakeLists.txt
文件中引入mstl
.
set(CMAKE_CXX_STANDARD 20)
# 若您安装的路径不在PATH环境变量内, 您可能还需要使用如下语句设置搜索路径
# list(APPEND CMAKE_PREFIX_PATH "...") # 把 ... 替换为mstl的安装路径
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # 开启调试模式下的部分运行时检查功能
find_package(mstl REQUIRED)
add_executable(mstl_test src/main.cpp)
target_link_libraries(mstl_test mstl::mstl)
接着, 在您的项目文件中包含mstl/mstl.h
#include <mstl/mstl.h>
构建与使用(不通过CMake
)
您可以直接把include/mstl
目录复制到任意地方.
在您的项目文件中包含mstl/mstl.h
#include <mstl/mstl.h>
并在编译时指定mstl
目录所在的目录.
g++ main.cpp -o main -I/path/to/the/directory
您也可以使用任何支持指定包含目录的构建工具.
贡献者
@Shiroan
@a1393323447
加入我们
我们欢迎您的积极参与, 您可以借由以下方法参与到本项目的开发之中:
- 就您认为可改进的地方, 希望实现的功能等提出issue, 我们随时欢迎您的指教.
- fork我们的仓库, 帮助我们完善文档和代码, 实现新功能.
作为一个全新的项目, MSTL还有很多不足.
我们期待您的加入, 让我们一起打造更强大的MSTL!