当你想让迭代器在返回之前进行迭代时,boost :: transform_iterator是非常好的.您传递它们一个一元函数,该函数转换底层迭代器的运算符*()的结果,然后转换迭代器返回:
template<typename Map> struct iterator_transform_traits_map_second { typedef typename Map::value_type value_type; typedef typename Map::mapped_type result_type; result_type& operator()( value_type& v) const {return v.second;} const result_type& operator()(const value_type& v) const {return v.second;} }; typedef boost::transform_iterator<iterator_transform_traits_map_second> transformed_iterator;
到现在为止还挺好.但.
这会导致什么混乱
你的同事喜欢这个闪亮的新工具,也开始使用它,很快有人会收集一个标题,到目前为止你已经想到了.这是我们的
> iterator_transform_traits_map_first
> iterator_transform_traits_map_second
> iterator_transform_traits_map_deref(取消引用任何容器的条目)
> iterator_transform_traits_map_deref_second(取消引用地图条目的第二个)
> iterator_transform_traits_map_dynamic_cast(执行一个dynamic_cast<>()任何容器的条目)
> iterator_transform_traits_map_any_second(在地图条目的第二个上执行any_cast<>())
当然,这样会留下很多有用的东西(因为还没有人需要它们),而且根本没有缩放.我的任务是编写一个迭代器来取消引用映射条目的第二个,并执行一个dynamic_cast(),我是被拒绝只添加一个iterator_transform_traits_map_dynamic_cast_deref_second并继续进行的.
我想要的是
相反,我正在尝试编写一些基本特征和编译时的组合特征,允许将其中的几个命名为模板参数,并简单地管道调用.理想情况下,我想要这样的东西:
typedef boost::transform_iterator< iterator_transform_traits< iter_transf_tr_second,iter_transf_tr_deref,iter_transf_tr_dynamic_cast<derived> > > transformed_iterator;
我目前的想法是递归地导出一个包装器模板,并且递归地调用所有的特征,将输出从一个传递到下一个.十年前我做了这样的事情,并且有一个基本的想法,如何做到这一点.但是,我最后一次这样做是步行的.也就是说,我自己实现了所有的模板元魔法.
这当然是愚蠢的,因为我们现在已经有boost.mpl,boost.fusion等,所以我宁愿雇用已经在那里的东西.但是,在修改了一个下午之后,很明显,在完成这个工作之前,我会很多学习.虽然我不反对学习所有这些,但我有一个人呼吸我的脖子,喜欢我做的,但说他需要拉插头,因为有这个截止日期…我现在有选择只是写这个damn iterator_transform_traits_map_dynamic_cast_deref_second,复制了大量已经腐烂十年的代码,建立在这个基础上,或者提出了一个干净的解决方案.
那是你进来的地方
问题
您将如何使用已经存在的复合特征来实现?
平台
然而,存在一个问题:我们正在嵌入式平台,并停留在GCC 4.1.2中,这意味着C 03,TR1和boost 1.52.没有可变的模板参数,没有decltype和所有那些花哨的东西.
解决方法
iterator_transform_traits.hpp
#include <boost/mpl/vector.hpp> #include <boost/mpl/back.hpp> #include <boost/mpl/front.hpp> #include <boost/mpl/fold.hpp> #include <boost/mpl/push_back.hpp> #include <boost/mpl/pop_front.hpp> #include <boost/fusion/adapted/mpl.hpp> #include <boost/fusion/container/vector/convert.hpp> #include <boost/fusion/algorithm/iteration/fold.hpp> #include <boost/ref.hpp> template<typename IteratorTraitsSequence,typename Container> class iterator_transform_traits { public: struct type { private: struct plcaholder_resolver { template<typename IteratorTraits,typename IteratorLambda> struct apply { typedef typename boost::mpl::push_back<IteratorTraits,typename boost::mpl::apply<typename boost::mpl::lambda<IteratorLambda>::type,typename boost::mpl::back<IteratorTraits>::type::result_type>::type>::type type; }; }; struct begin_value { typedef typename Container::value_type result_type; }; typedef typename boost::mpl::pop_front<typename boost::mpl::fold<IteratorTraitsSequence,boost::mpl::vector<begin_value>,plcaholder_resolver>::type>::type iterator_traits; public: typedef typename boost::mpl::front<iterator_traits>::type::value_type value_type; typedef typename boost::mpl::back<iterator_traits>::type::result_type result_type; public: struct recursive_iterator_modifier { template<class> struct result; template<class F,typename CurrentResult,typename IteratorTrait> struct result<F(CurrentResult&,const IteratorTrait&)> { typedef typename IteratorTrait::result_type& type; }; template<class F,typename IteratorTrait> struct result<F(const CurrentResult&,const IteratorTrait&)> { typedef const typename IteratorTrait::result_type& type; }; template<class F,typename IteratorTrait> struct result<F(const boost::reference_wrapper<CurrentResult>&,const IteratorTrait&)> { typedef typename IteratorTrait::result_type& type; }; template<typename CurrentResult,typename IteratorTrait> typename IteratorTrait::result_type& operator()(CurrentResult& modified,const IteratorTrait& it) { return (it(modified)); } template<typename CurrentResult,typename IteratorTrait> const typename IteratorTrait::result_type& operator()(const CurrentResult& modified,typename IteratorTrait> typename IteratorTrait::result_type& operator()(const boost::reference_wrapper<CurrentResult>& modified,const IteratorTrait& it) { return (it(modified.get())); } }; public: result_type& operator()(value_type& v) const { return boost::fusion::fold(iterator_traits_vector_,boost::ref(v),recursive_iterator_modifier()); } const result_type& operator()(const value_type& v) const { return boost::fusion::fold(iterator_traits_vector_,recursive_iterator_modifier()); } private: typedef typename boost::fusion::result_of::as_vector<iterator_traits>::type iterator_traits_vector; iterator_traits_vector iterator_traits_vector_; }; };
你这样使用:
#include <map> #include <string> #include <iostream> #include <typeinfo> #include "iterator_transform_traits.hpp" template<typename Pair> struct iterator_transform_traits_map_second { typedef Pair value_type; typedef typename Pair::second_type result_type; result_type& operator()( value_type& v) const {return v.second;} const result_type& operator()(const value_type& v) const {return v.second;} }; template<typename Dereferenced> struct iterator_transform_traits_deref {}; template<typename Dereferenced> struct iterator_transform_traits_deref<Dereferenced*> { typedef Dereferenced* value_type; typedef Dereferenced result_type; result_type& operator()( value_type& v) const {return *v;} const result_type& operator()(const value_type& v) const {return *v;} }; typedef std::map<std::string,std::string*> string_ptr_map; typedef iterator_transform_traits<boost::mpl::vector<iterator_transform_traits_map_second<boost::mpl::_1>,iterator_transform_traits_deref<boost::mpl::_1> >,string_ptr_map>::type Transformer; typedef boost::transform_iterator<Transformer,string_ptr_map::iterator> string_ptr_map_second_deref_iterator; int main() { string_ptr_map map; map["key1"] = new std::string("value1"); map["key2"] = new std::string("value2"); map["key3"] = new std::string("value3"); for(string_ptr_map_second_deref_iterator it(map.begin(),Transformer()),ite(map.end(),Transformer()); it != ite; ++it) { std::cout << *it << std::endl; } return 0; }
现在一些信息:
>每个iterator_transform_trait必须在其将要作为参数接收的value_type上进行模板化,而不是在容器上,否则您不能自动链接它们.
>使用boost :: mpl和boost :: fusion有很多小编程操作,我希望元函数名称是足够明确的,随时问任何问题
>您需要使用mpl序列作为模板参数,因为您无法访问C 11和可变模板.
>这是一个在线编译版本:http://rextester.com/ZIYG56999>这是一个很有趣的运动,让我头疼了:)