Monster
高级C++模板元编程框架
概述
#include <cstdint>
#include <monster.hpp>
using namespace monster;
int main(int argc, char* argv[])
{
// 将相同元素在序列中排列相邻,保持相对顺序
using a1 = adjacent_t<std::tuple<char, double, char, int, double>>;
using a2 = adjacent_t<std::index_sequence<4, 3, 0, 3, 2, 4, 5, 3>>;
static_assert(std::is_same_v<a1, std::tuple<char, char, double, double, int>>);
static_assert(std::is_same_v<a2, std::index_sequence<4, 4, 3, 3, 3, 0, 2, 5>>);
// Boyer-Moore-Horspool (BMH)算法在一个序列中搜索另一个序列的出现
using b1 = bmh_t<std::tuple<int, char, int>, std::tuple<int, int, char, int, char, int, char, int>>;
using b2 = bmh_t<std::integer_sequence<int, 7, 5>, std::integer_sequence<int, 7, 5, 4, 0, 7, 5, 9>>;
static_assert(std::is_same_v<b1, std::index_sequence<1, 3, 5>>);
static_assert(std::is_same_v<b2, std::index_sequence<0, 4>>);
// Knuth–Morris–Pratt (KMP)算法在一个序列中搜索另一个序列的出现
using k1 = kmp_t<std::tuple<int, char, int>, std::tuple<int, int, char, int, char, int, char, int>>;
using k2 = kmp_t<std::integer_sequence<int, 7, 5>, std::integer_sequence<int, 7, 5, 4, 0, 7, 5, 9>>;
static_assert(std::is_same_v<k1, std::index_sequence<1, 3, 5>>);
static_assert(std::is_same_v<k2, std::index_sequence<0, 4>>);
// 在序列中找到第K小的元素(k == 2)
using min1 = select_t<2, std::tuple<short, int, double, int, char>>;
using min2 = select_t<2, std::integer_sequence<int, -2, 1, 0, -7, 4, 3>>;
static_assert(std::is_same_v<min1, short>);
static_assert(std::is_same_v<min2, c_<-2>>);
// 在序列中找到第K大的元素(k == 2)
using max1 = select_t<2, std::tuple<short, int, double, int, char>, greater_equal_t>;
constexpr auto max2 = select_v<2, std::integer_sequence<int, -2, 1, 0, -7, 4, 3>, greater_equal_t>;
static_assert(std::is_same_v<max1, int>);
static_assert(max2 == 3);
// 返回序列中特定索引的元素
using e1 = element_t<1, std::tuple<char, double, int>>;
using e2 = element_t<3, std::integer_sequence<int, 1, -2, 7, 4>>;
constexpr auto e3 = element_v<3, std::integer_sequence<int, 1, -2, 7, 4>>;
static_assert(std::is_same_v<e1, double>);
static_assert(std::is_same_v<e2, c_4>);
static_assert(e3 == 4);
// 从序列中移除重复元素,保留第一次出现
using u1 = unique_t<std::tuple<int, char, int, double>>;
using u2 = unique_t<std::integer_sequence<int, 2, 2, 3, 4, 3>>;
static_assert(std::is_same_v<u1, std::tuple<int, char, double>>);
static_assert(std::is_same_v<u2, std::integer_sequence<int, 2, 3, 4>>);
// 交换序列中特定索引的元素
using s1 = swap_t<1, 3, std::tuple<int, double, char, float>>;
using s2 = swap_t<0, 2, std::integer_sequence<int, 1, -2, 7, 4>>;
static_assert(std::is_same_v<s1, std::tuple<int, float, char, double>>);
static_assert(std::is_same_v<s2, std::integer_sequence<int, 7, -2, 1, 4>>);
// 按值对序列中的元素进行排序
using s3 = quick_sort_t<std::tuple<double, short, double, int, char, char, double>>;
using s4 = quick_sort_t<std::integer_sequence<int, 2, 1, 0, -3, 4, 1, -7, 5, -2>>;
static_assert(std::is_same_v<s3, std::tuple<char, char, short, int, double, double, double>>);
static_assert(std::is_same_v<s4, std::integer_sequence<int, -7, -3, -2, 0, 1, 1, 2, 4, 5>>);
// 按索引对序列中的元素进行排序
using s5 = sort_index_t<std::tuple<double, short, double, int, char, char, double>>;
using s6 = sort_index_t<std::integer_sequence<int, 2, 1, 0, -3, 4, 1, -7, 5, -2>>;
static_assert(std::is_same_v<s5, std::index_sequence<4, 5, 1, 3, 6, 2, 0>>);
static_assert(std::is_same_v<s6, std::index_sequence<6, 3, 8, 2, 1, 5, 0, 4, 7>>);
// 反转序列中元素的顺序
using r1 = reverse_t<std::tuple<float, double, int, short>>;
using r2 = reverse_t<std::integer_sequence<int, 1, 0, 2, -2, 7, 6>>;
static_assert(std::is_same_v<r1, std::tuple<short, int, double, float>>);
static_assert(std::is_same_v<r2, std::integer_sequence<int, 6, 7, -2, 2, 0, 1>>);
// 递归地反转序列元素的顺序
using r3 = reverse_recursive_t<std::tuple<int, std::tuple<int, std::tuple<char, short>>, char>>;
using r4 = reverse_recursive_t<std::tuple<char, std::integer_sequence<int, 7, 2, 0, 4, 8>, int>>;
static_assert(std::is_same_v<r3, std::tuple<char, std::tuple<std::tuple<short, char>, int>, int>>);
static_assert(std::is_same_v<r4, std::tuple<int, std::integer_sequence<int, 8, 4, 0, 2, 7>, char>>);
// 旋转序列中[begin, middle, end)范围内的元素
using r5 = rotate_t<0, 2, 5, std::tuple<int, char, double, float, int64_t>>;
using r6 = rotate_t<2, 4, 7, std::integer_sequence<int, 9, 8, 1, 2, 3, 4, 5, 7, 6>>;
static_assert(std::is_same_v<r5, std::tuple<double, float, int64_t, int, char>>);
static_assert(std::is_same_v<r6, std::integer_sequence<int, 9, 8, 3, 4, 5, 1, 2, 7, 6>>);
// 返回序列中[begin, end)范围内的元素
using r7 = range_t<1, 5, std::tuple<int, char, float, double, int, short>>;
using r8 = range_t<2, 6, std::integer_sequence<int, 1, 2, -2, 4, 3, 5, 8, -5>>;
static_assert(std::is_same_v<r7, std::tuple<char, float, double, int>>);
static_assert(std::is_same_v<r8, std::integer_sequence<int, -2, 4, 3, 5>>);
return 0;
}
## 简介
Monster是一个元编程库,它是仅头文件的、可扩展的,并且面向现代C++。
它以纯类型编程的形式展示了编译时算法、序列和高阶元函数。
Monster提供了概念基础和一套广泛的强大而连贯的工具,使得在现代C++中进行显式的高级模板元编程(TMP)变得简单而愉快。
## 编译器要求
该库依赖于C++20编译器和标准库,但不需要其他任何东西。
更具体地说,Monster需要支持以下C++20特性(非详尽列举)的编译器/标准库:
- 概念
- Lambda模板
- <type_traits>头文件中的所有C++20类型特征
## 构建
Monster是仅头文件的。要使用它,只需在源文件中添加必要的`#include`行,如下所示:
```cpp
#include <monster.hpp>
要使用cmake构建示例,请cd
到项目根目录并设置构建目录:
mkdir build
cd build
cmake ..
编译并安装可执行文件:
make -j4
make install
可执行文件现在位于项目根目录的bin
目录中。
示例也可以使用build.sh
脚本构建,只需运行它,可执行文件将被放置在/tmp
目录中。
文档
你可以在Guidelines.md在线浏览文档。 文档涵盖了你所需要的一切,包括安装库、目录和带有示例的广泛参考部分。
完整示例
请参阅Tutorial.md。
许可证
Monster的许可证为Boost软件许可证1.0版。