先看看twice的定义:twice(f, x) := f(f(x)),要求提供一个twice的实现,然后从boost::add_pointer出发,得到add_two_pointers。
书中给出的twice<F, X>要求F是元函数类(metafunction class),而add_pointer是一个元函数,因此还要手工从boost::add_pointer生成相应的元函数类,然后才可以使用twice。
代码如下:
| struct add_pointer_f{ template <class T> struct apply : boost::add_pointer<T> {};}; template <class F, class X>struct twice : F::template apply<typename F::template apply<X>::type>{}; template <class X>struct add_two_pointers : twice<add_pointer_f, X>{}; |
接着,书中示例了如何用mpl::lambda元函数来从boost::add_pointer就地生成twice所需的元函数类,这样就可以省掉add_pointer_f的手工定义。代码如下:
| template <class F, class X>struct twice : F::template apply<typename F::template apply<X>::type>{}; template <class X>struct add_two_pointers : twice<typename mpl::lambda<boost::add_pointer<_1> >::type, X>{}; |
最后,书中展示了如何用mpl::apply元函数替换掉在twice中的手工调用apply。代码如下:
| template <class F, class X>struct twice : mpl::apply<F, typename mpl::apply<F, X>::type>{}; template <class X>struct add_two_pointers : twice<typename mpl::lambda<boost::add_pointer<_1> >::type, X>{}; |
以上几种实现方法,里面的template、typename、::type还有类括号一大堆,看得我脑袋发晕。我想,为什么twice<F, X>中的F一定要是class,而不能是template呢?C++模板不是还支持模板模板参数(template template parameter)吗?如果让F可以是一个模板模板参数,代码应该更简单、直接,也更容易读一些。如下:
| template <template <typename> class F, class X>struct twice : F< typename F<X>::type >{}; template <class X>struct add_two_pointers : twice<boost::add_pointer, X>{}; |
以上四种实现方法,都可以顺利通过以下测试:
| int main(){ typedef add_two_pointers<int>::type intpp;BOOST_STATIC_ASSERT((boost::is_same<intpp , int**>::value));} |
我还是比较喜欢最后一种写法,你呢?
