高级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版。