Copyright © 2004, 2005 Arkadiy Vertleyb, Peder Holt
根据 Boost 软件许可证 1.0 版分发。(请参阅随附文件 LICENSE_1_0.txt 或访问 https://boost.ac.cn/LICENSE_1_0.txt 副本)
目录
如今,许多模板库都提供了对象生成器,以利用 C++ 模板参数推导功能来简化对象的创建。考虑 `std::pair`。为了实例化这个类模板并创建一个该实例化的临时对象,必须提供模板参数以及构造函数的参数。
std::pair<int, double>(5, 3.14159);
为避免这种重复,STL 提供了 `std::make_pair` 对象生成器。当使用它时,模板参数的类型将从提供的函数参数推导出来。
std::make_pair(5, 3.14159);
对于临时对象来说,这已经足够了。但是,当需要分配一个命名对象时,问题又出现了。
std::pair<int, double> p(5, 3.14159);
对象生成器不再有用
std::pair<int, double> p = std::make_pair(5, 3.14159);
能够从初始化表达式(右侧)推导出对象(左侧)的类型将是很方便的,但目前的 C++ 语法不允许这样做。
上面的例子演示了问题的本质,但没有展示其规模。许多库,尤其是表达式模板库,会创建真正复杂类型的对象,并花费大量精力来通过对象生成器隐藏这种复杂性。考虑一个 Boost.Lambda 的仿函数。
_1 > 15 && _2 < 20
如果有人想要分配一个这种看起来无害的仿函数的命名副本,她将不得不指定类似以下的内容。
lambda_functor< lambda_functor_base< logical_action<and_action>, tuple< lambda_functor< lambda_functor_base< relational_action<greater_action>, tuple< lambda_functor<placeholder<1> >, int const > > >, lambda_functor< lambda_functor_base< relational_action<less_action>, tuple< lambda_functor<placeholder<2> >, int const > > > > > > f = _1 > 15 && _2 < 20;
不太优雅。为了解决这个问题(以及其他一些问题),C++ 标准委员会正在考虑对标准语言进行一些补充,例如 `typeof`/`decltype` 和 `auto`(参见 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1607.pdf)。
`typeof` 运算符(或 `decltype`,它是 `typeof` 的一个稍有不同的变体)允许在编译时确定表达式的类型。使用 `typeof`,可以极大地简化上面的例子。
typeof(_1 > 15 && _2 < 20) f = _1 > 15 && _2 < 20;
好多了,但仍有一些重复。`auto` 类型解决了剩余的问题。
auto f = _1 > 15 && _2 < 20;
Boost.Typeof 库的目的是提供一个基于库的解决方案,可以在语言级设施添加到标准并广泛可用之前使用。