发信人: huxw (米老鸭和唐老鼠), 信区: Programming
标 题: boost::iterator_adaptor (II)
发信站: BBS 水木清华站 (Sun May 19 22:27:09 2002)
申明:这里只是一种技巧。从某种眼光看来过于花哨。所以我只是介绍
介绍,并不是要鼓励大家都这样去折磨你的编译器。 ;)
II) 简化复杂的模板参数列表
iterator模版中用到很多模版参数, value, pointer, reference等等,
他们之间并非没有联系. 事实上, 这些模版参数的缺省值本来都是推算
出来的.
template <class Base, class Policies,
class Value = typename std::iterator_traits<Base>::value_type,
class Reference = typename iterator_defaults<Base,Value>::reference,
class Pointer = typename iterator_defaults<Base,Value>::pointer,
class Category = typename std::iterator_traits<Base>::iterator_category,
class Distance = typename std::iterator_traits<Base>::difference_type
>
很合理是吧, 但是有没有想过如果我们并不需要提供那么多模版参数的
时候总需要输入那么多, 会怎么样? 有没有想过如果这样的推算推不出
结果来怎么办? 所以最后我们看到的代码是酱紫的.
template <class Base, class Policies,
class Value = ::boost::detail::default_argument,
class Reference = ::boost::detail::default_argument,
class Pointer = ::boost::detail::default_argument,
class Category = ::boost::detail::default_argument,
class Distance = ::boost::detail::default_argument
> struct iterator_adaptor
这样的代码能带来什么好处呢? 就是我们可以酱紫实例化模版了.
iterator_adaptor<BaseIterator,
transform_iterator_policies<AdaptableUnaryFunction>,
iterator_category_is<std::input_iterator_tag>,
value_type_is<val_t>, reference_is<val_t>
> myite;
注意到了嘛, 模版参数根本不和我们声明的时候相同. ;) 多奇妙啊,
我们用函数缺省参数的时候都不能这样.
声明: int foo(int i, long j = 0, double k = 9.8);
而调用的时候:foo(1, k = 8.7); // 错误
但是模版实例化的时候可以. 原因就在于iterator_adaptor开始时做的
手脚. 他用了一个iterator_traits_gen的模板. 这个模版并不在乎我
们给的模版参数的意义, 他只是简单的构建一个typelist, 然后利用
find_param从typelist中把需要的类型捡出来.
typedef detail::cons_type< typename make_arg<value_type_tag, Value>::type,
detail::cons_type<typename make_arg<reference_tag, Reference>::type,
detail::cons_type<typename make_arg<pointer_tag, Pointer>::type,
detail::cons_type<typename make_arg<iterator_category_tag, Category>::type,
detail::cons_type<typename make_arg<difference_type_tag, Distance>::type,
end_of_list> > > > > ArgList;
typedef typename find_param<ArgList, value_type_tag>::type Val;
typedef typename find_param<ArgList, difference_type_tag>::type Diff;
typedef typename find_param<ArgList, iterator_category_tag>::type Cat;
typedef typename find_param<ArgList, pointer_tag>::type Ptr;
typedef typename find_param<ArgList, reference_tag>::type Ref;
结合上面的代码中出现的value_type_is类似的方法, 你一定直觉到make_arg
有问题. 确实,
template<class T> struct is_named_parameter {
enum { value = false; }
};
template <class T> struct is_named_parameter<value_type_is<T> > { enum { value = true }; };
template <class Key, class Value>
struct make_arg {
enum { is_named = is_named_parameter<Value>::value };
//我们使is_named_parameter对value_type_is类型做特化, 那么.... 呵呵
typedef typename if_true<(is_named)>::template
then<make_named_arg, //如果is_named成功, 那么结果就是make_named_arg::type
make_key_value>::type Make; //反之就是make_key_valye::type
typedef typename Make::template select<Key, Value>::type type;
};
struct make_named_arg {
template <class Key, class Value>
struct select { typedef typename Value::type type; };
}; //如果用value_type_is<T>做模版参数
struct make_key_value {
struct make_named_arg {
template <class Key, class Value>
struct select { typedef typename Value::type type; };
}; //如果用value_type_is<T>做模版参数
struct make_key_value {
template <class Key, class Value>
struct select { typedef detail::cons_type<Key, Value> type; };
}; //如果用T做模版参数
是不是有了一点心得了? 那么长的篇幅, 看到这里真不容易. 既然都看
到这里了, 就帮个忙, 给peach写一封信骚扰, 请他写写
boost::function吧. ;)
--
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
※ 修改:·huxw 於 May 19 22:28:23 修改本文·[FROM: 166.111.172.6]
※ 来源:·BBS 水木清华站 bbs.edu.cn·[FROM: 166.111.172.6]