试想一下,在创建围绕某个SQL数据库接口的一个包装。你决定 boost::any将完全匹配数据库表的一个单元格的要求。其他某个程序员会使用你的类,他的任务将是从数据库中获得行,计算在一行的算术类型的总和。 代码类似于下面这样: 如果编译并运行这个例子,会输出一个正确的答案: (数据库中算术类型行的合计是:20.1) 还记得阅读operator()的实现时你的想法是什么吗?我猜你的想法是,“double, long, short, unsigned和其他类型怎么办?”将使用你的接口的一个程序员的脑海中也有同样的想法。所以你需要在文档中仔细记录你的cell_t存储的值,或阅读下面章节中描述的更优雅的解决方案。 准备 如果你不熟悉Boost.Variant和Boost.Any库,强烈建议先阅读前面两个秘笈。 做法 Boost.Variant库实现了一个访客编程模式来访问存储的数据,这比通过 boost::get<>获取值安全得多。这种模式迫使程序员处理好每个变体类型,否则代码将编译失败。可以通过boost::apply_visitor函数使用这个模式,这个函数采用访客函数化对象(functional object)作为第一个参数,并用一个变体作为第二个参数。访客函数化对象必须派生自boost::static_visitor<T>类,其中T是被访客返回的一个类型。访客对象必须为变体中存储的每种类型备有重载 operator()。 下面将cell_t类型改为boost::variant<int, float, string>并修改我们的例子: 工作原理 Boost.Variant库在编译时会产生一个大的switch语句,which的每个case将对变体的类型列表中的单个类型调用一个访客。在运行时,可以使用which()得到存储类型的索引,并将跳转到switch语句中正确的case处。某些像这样的东西将为boost::variant<int, float, std::string>产生: 在这里,address()函数返回指向boost::variant<int, float, std::string>内部存储的一个指针。 还有更多 如果将这个例子与这个秘笈的第一个例子比较,将看到boost::variant有以下优点: 知道变量可以存储什么类型。 如果一个SQL接口库的作者添加或修改了一个变体持有的一个类型,会得到一个编译时错误,而不是不正确的行为。 参见 学完第4章的一些秘笈后,就能够使访客对象很通用,因此,即使基础类型变化了,它也有能力正确地工作。 Boost的官方文档中包含更多的例子和Boost.Variant的一些其他功能的描述,可在以下地址获得该资料:http://www./doc/libs/1_53_0/doc/html/variant.html。 【责任编辑:book TEL:(010)68476606】
|
|
来自: 码农书馆 > 《C++Style》