提问人:sbi 提问时间:1/30/2014 最后编辑:Communitysbi 更新时间:1/31/2014 访问量:286
为 boost 的转换迭代器寻找复合特征模式
Looking for a composite traits pattern for boost's transform iterators
问:
环境
当你想让迭代器在返回之前对它们正在迭代的内容进行调整时,这非常好。你向他们传递一个一元函数,该函数转换底层迭代器的结果,然后转换迭代器返回:boost::transform_iterator
operator*()
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
(取消引用地图条目的second
)iterator_transform_traits_map_dynamic_cast
(执行任何容器的条目)dynamic_cast<>()
iterator_transform_traits_map_any_second
(在地图上执行条目的any_cast<>()
second
)
当然,这遗漏了很多有用的(因为还没有人需要它们),而且它根本没有扩展。我的任务只是编写一个迭代器来取消引用地图条目并执行一个,而我就是我,拒绝添加一个并继续前进。second
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 等,所以我宁愿使用已经存在的东西。然而,在修补了一个下午之后,很明显,在我完成这项工作之前,我还有很多东西要学。虽然我不反对学习所有这些,但我有一个人在我的脖子上呼吸,他喜欢我所做的事情,但说他无论如何都需要拔掉插头,因为有这个截止日期......我现在可以选择只写该死的,复制大量已经腐烂了十年的代码并在此基础上构建,或者想出一个干净的解决方案。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 CurrentResult, typename IteratorTrait>
struct result<F(const CurrentResult&, const IteratorTrait&)>
{
typedef const typename IteratorTrait::result_type& type;
};
template<class F, typename CurrentResult, 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, const IteratorTrait& it)
{
return (it(modified));
}
template<typename CurrentResult, 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_, boost::ref(v), 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
- 您需要使用序列作为模板参数,因为您无权访问 C++11 和可变参数模板。
mpl
- 这是一个在线编译版本:http://rextester.com/ZIYG56999
- 这是一个有趣的练习,让我有些头疼:)
评论