boost::fusion的目的是什么?

4

我一整天都在阅读关于boost::fusion的笔记和观看视频,但是我仍然对其中一些方面感到困惑。

比如说,boost::fusion::has_key<S> 函数的目的是什么?将尽可能多的编程工作转移到编译时,这是这个库的设计理念吗?因此,几乎任何一个 boost::fusion 函数都与运行时版本相同,只不过现在它会在编译时进行评估(我们假定在编译时执行更多操作是好的)。

与 boost::fusion 相关的是,我也有点困惑为什么元函数总是返回类型。这是为什么呢?


6
我更愿意在编译时发现错误,而不是在运行时。 - Captain Obvlious
这是一个用于元组的STL。如果你将类映射到元组中,你可以在编译时使用它进行反射。 - gnzlbg
2个回答

6
另一种看待boost::fusion的方式是将其视为“贫穷人的内省”库。boost::fusion最初的动机来自于boost::spirit解析器/生成器框架,特别是需要支持所谓的“解析器属性”。假设你有一个CSV字符串需要解析:aaaa, 1.1。这个字符串解析成的类型可以描述为“字符串和双精度浮点数的元组”。我们可以在“普通”的C++中定义这样的元组,可以使用旧式结构体(struct {string a; double b;})或者较新的tuple。唯一缺失的就是某种适配器,它将允许传递具有任意组合的元组(和其他一些类型)到统一的解析器接口,并希望它能够理解它,而不传递任何带外信息(例如scanf使用的字符串解析模板)。这就是boost::fusion的作用所在。构造“fusion序列”的最直接方法是适应一个普通的结构体。
struct a {
    string s;
    double d;
};
BOOST_FUSION_ADAPT_STRUCT(a, (string, s)(double, d))

"ADAPT_STRUCT"宏添加了必要的信息,使解析器框架(在本例中)能够“迭代”struct a的成员,以回答以下问题:
  1. 我刚刚解析了一个字符串。我可以将它分配给struct a的第一个成员吗?

  2. 我刚刚解析了一个双精度数。我可以将它分配给struct a的第二个成员吗?

  3. struct a中是否还有其他成员,或者我应该停止解析?

显然,这个基本示例可以进一步扩展(boost::fusion提供了这种能力),以处理更复杂的情况:
  1. 变体 - 假设解析器可能会遇到字符串或双精度数,并希望将其分配给struct a的正确成员。BOOST_FUSION_ADAPT_ASSOC_STRUCT来拯救(现在我们的解析器可以询问:“struct a的哪个成员是双精度类型?”)。

  2. 转换 - 我们的解析器可以被设计为接受某些类型作为参数,但程序的其余部分已经发生了很大变化。然而,fusion元函数可以方便地用于将新类型适应于旧现实(或反之亦然)。

boost::fusion的其余功能自然地遵循上述基本原则。当需要将“松散I/O数据”转换为C++程序操作的强类型/结构化数据(如果效率是关注的重点)时,fusion真正发挥作用。它是spirit::qi和spirit::karma成为如此高效(可能是最快的)I/O框架的启动因素。

4

Fusion作为编译时和运行时容器和算法之间的桥梁存在。您可能希望将一些处理移动到编译时,但如果您确实希望这样做,Fusion可能会有所帮助。我认为它没有一个特定的宣言要尽可能多地移动到编译时,尽管我可能错了。

元函数返回类型,因为模板元编程并不是有意创造出来的。人们差不多是偶然发现C++模板可以用作编译时编程语言。元函数是从模板参数到模板实例化的映射。截至C++03,有两种模板(类和函数),因此元函数必须“返回”类或函数。类比函数更有用,因为您可以将值等放入其静态数据成员中。

C++11添加了另一种模板(用于typedefs),但这对于元编程来说有点无关紧要。对于编译时编程更重要的是,C++11添加了constexpr函数。它们专门为此目的设计,并像普通函数一样返回值。当然,它们的输入不是类型,因此它们不能像模板那样将类型映射到其他东西。因此,在这个意义上,它们缺少元编程的“元-”部分。它们“只是”普通C++函数的编译时评估,而不是元函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接