首页
/ MPL11 技术文档

MPL11 技术文档

2024-12-28 19:35:35作者:农烁颖Land

1. 安装指南

MPL11 是一个头文件库。要在您的项目中使用它,只需将 include 目录添加到编译器的头文件搜索路径中即可。

该库没有依赖项,甚至不依赖标准库。但是,它需要一个支持 C++14 的编译器。测试套件在以下编译器中通过:

  • clang 版本 3.4
  • clang 版本 3.5.0
  • GCC 4.9.0 20140302 (实验性)
  • Apple LLVM 版本 5.1 (clang-503.0.38)

要编译单元测试,您还需要安装 [CMake]。安装完成后,您可以进入项目根目录并执行以下命令:

$ mkdir build
$ cd build
$ cmake ..
$ make tests    # 编译单元测试。

精简版本

MPL11 也提供了一个精简版本。要使用它,只需包含 boost/mpl11.min.hpp 头文件,其中包含整个库。请注意,精简头文件不得与其他库头文件一起使用。

2. 项目使用说明

MPL11 是一个基于 C++11 的库,提供用于解决复杂模板元编程问题的可组合、高级基元。该库围绕几个核心概念构建;本教程的目的是介绍这些概念,而库提供的工具则留给了 参考文档

本教程假设您对模板元编程和基本函数编程概念有很好的理解。此外,了解 Boost.MPL 库也将有所帮助。但是,MPL11 在很多方面都与 Boost.MPL 有所不同,因此在将知识从一个库转移到另一个库时,需要检查文档。

3. 项目 API 使用文档

以下是 MPL11 库的一些关键概念和使用的简要说明。

Metafunctions

非正式地,元函数是一个模板,表示一个编译时函数,它接受类型作为参数并返回一个类型作为结果。来自 MPL 的读者应该注意,这里的正式定义与 MPL 的定义不同。

正式地,设 f 为一个具有任意数量类型模板参数的 C++ 模板,且仅具有类型模板参数。如果存在类型 x1, ..., xn 使得 f<x1, ..., xn>::type 是一个有效的类型名,则 f 是一个 元函数。在这种情况下:

  • x1, ..., xnf参数
  • 形成特化 f<x1, ..., xn> 被称为 暂停 fx1, ..., xn
  • 特化 f<x1, ..., xn> 被称为 thunksuspension
  • Thunk 的嵌套 ::type 被称为 thunk 的 结果。如果 thunk 的形式为 f<x1, ..., xn>,我们也可以说它是 fx1, ..., xn 的结果。
  • 获取 thunk 的结果称为 评估 thunk。如果 thunk 的形式为 f<x1, ..., xn>,我们也可以说 调用 fx1, ..., xn应用 fx1, ..., xn
  • 元函数的 arity 是它可以被调用的参数数量。具有 n 个参数的元函数被称为 n-ary 元函数。
  • 一个可以接受任意数量参数的元函数被称为 可变参数。根据定义,可变参数元函数对于任何非负整数 n 都是 n-ary。

重要的是要注意这个定义与 Boost.MPL 给出的定义之间的区别。根据这个定义,元函数永远不能是普通的 C++ 类型;它必须始终是模板。因此,Boost.MPL 实现为非模板类的零元元函数不被视为元函数。

以下是一些示例:

// 一个一元元函数。
template <typename x>
struct unary { struct type; };

// 一个二元元函数。
template <typename x, typename y>
struct binary { struct type; };

// 一个可变参数元函数。
template <typename ...>
struct variadic { struct type; };

// 一个零元元函数。它只能被调用 0 个参数,因此它是 0-ary(零元)。
template <typename ...> struct nullary;
template <> struct nullary<> { struct type; };

// 不是 MPL11 的元函数;它不是模板!
struct MPL_nullary { struct type; };

// 不是元函数;它从不具有结果(一个嵌套的 ::type)!
template <typename ...>
struct no_result { };

Boxed Types

非正式地,boxed 类型是一个尚未被评估的类型。因此,在知道boxed类型的实际“值”之前,必须评估它,这个过程称为解包。

正式地,对于任意的 C++ 类型 T,一个 boxed T 是一个任意的 C++ 类型 B,使得 B::typeT。在这种情况下,B 被称为 box(of T)和解包 T 的过程称为 unboxing T

struct T;
struct B { using type = T; }; // 一个boxed T(等价于T的box)

B::type; // 解包T

相反,将任意类型 T 包裹在类型 B 中,使得 B::typeT 被称为 boxing T(到 B 或用 B)。重要的是要注意 B 可能依赖于 T,没有这一点,boxed 将失去其意义。

struct T;

template <typename t>
struct B { using type = t; };

B<T>; // 将T boxing到B

请注意,类型可以被boxed任意次。这可能不是很有用,但定义足够通用以允许它。

B<B<T>>; // 这是一个“B<T>的box”,即“T的box的box”

存在一个特殊的boxed类型名为 undefined(有时称为_bottom_),其特点是当它被解包时,即使在 SFINAE-able 上下文中也会导致编译时错误。undefined 可以被视为无效值或失败的计算结果。

以下是一些示例来说明前面的定义:

// 这个模板接受一个任意类型T并boxed它。
template <typename T>
struct box {
    using type = T;
};

// 这些不是boxed。
class x;
struct y { char foo; };
char;
box<char>::type;

// 这些是boxed类型。
box<char>;                          // 一个boxed `char`
box<box<char>>;                     // 一个boxed `box<char>`
box<box<char>>::type;               // 一个boxed `char`
struct x { using type = char; };    // 一个boxed `char`
struct y { struct type; };          // 一个boxed `y::type`
struct z { using type = z; };       // 自引用?为什么不!

重要的是要注意,boxed T 有很多不同的表示。这使得boxed类型之间的等价关系变得有点复杂。考虑以下内容:

struct T;
struct B1 { using type = T; }; // 一个boxed T
struct B2 { using type = T; }; // 另一个boxed T

当然,B1B2 在他们boxed的类型上是等价的,因为他们都boxed了同一个类型 T。但是,B1B2 在 C++ 类型系统上是不等价的,因为他们是不同的类型。现在,这很重要,因为它告诉我们不能使用模式匹配来定义一个接受boxed类型作为参数的元函数。确实,由于boxed类型的表示不是唯一的,我们无法预知我们的参数将具有什么形式,因此无法进行模式匹配。考虑以下内容:

// B 应该是一个boxed类型。
template <typename B>
struct f;

// 这应该处理boxed chars,但我们不知道boxed char可能看起来像什么!
template <>
struct f<????> {
    // ...
};

现在,我们可能会尝试这样做:

// box 是我们之前定义的模板。它接受一个任意类型并boxed它。
template <>
struct f<box<char>> {
    // ...
};

但是后来...

template <typename T>
struct bad {
    using type = T;
};

// 如预期那样工作
f<box<char>>::type;

// 即使 bad<char> 显然是一个boxed char,也不工作
f<bad<char>>::type;

相反,我们可能需要进行更复杂的操作,如:

template <typename T>
struct f_impl;

template <>
struct f_impl<char> {
    using type = ...;
};

template <typename B>
struct f
    : f_impl<typename B::type>
{ };

f<box<char>>::type; // 工作
f<bad<char>>::type; // 也工作

有趣的是,boxed 类型和 thunks 之间有很多相似之处。实际上,thunk不过是通过 suspending 一个元函数形成的boxed类型。因此,每当boxed类型被期望时,都可以使用 thunk 代替。

登录后查看全文
热门项目推荐

热门内容推荐

最新内容推荐

项目优选

收起
docsdocs
OpenHarmony documentation | OpenHarmony开发者文档
Dockerfile
153
1.98 K
kernelkernel
deepin linux kernel
C
22
6
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
503
39
communitycommunity
本项目是CANN开源社区的核心管理仓库,包含社区的治理章程、治理组织、通用操作指引及流程规范等基础信息
331
10
openGauss-serveropenGauss-server
openGauss kernel ~ openGauss is an open source relational database management system
C++
146
191
openHiTLSopenHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
992
395
nop-entropynop-entropy
Nop Platform 2.0是基于可逆计算理论实现的采用面向语言编程范式的新一代低代码开发平台,包含基于全新原理从零开始研发的GraphQL引擎、ORM引擎、工作流引擎、报表引擎、规则引擎、批处理引引擎等完整设计。nop-entropy是它的后端部分,采用java语言实现,可选择集成Spring框架或者Quarkus框架。中小企业可以免费商用
Java
8
0
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
193
277
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
938
554
金融AI编程实战金融AI编程实战
为非计算机科班出身 (例如财经类高校金融学院) 同学量身定制,新手友好,让学生以亲身实践开源开发的方式,学会使用计算机自动化自己的科研/创新工作。案例以量化投资为主线,涉及 Bash、Python、SQL、BI、AI 等全技术栈,培养面向未来的数智化人才 (如数据工程师、数据分析师、数据科学家、数据决策者、量化投资人)。
Python
75
70