当你想让迭代器在返回之前处理它们正在迭代的内容时,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;
到目前为止,还不错。但是。
您的同事喜欢这个 Shiny 的新工具,并且也开始使用它,很快就会有人在标题中收集您到目前为止所提出的所有内容。这是我们的:
iterator_transform_traits_map_first iterator_transform_traits_map_second iterator_transform_traits_map_deref (取消引用任何容器的条目)iterator_transform_traits_map_deref_second (取消引用 map 条目的 second )iterator_transform_traits_map_dynamic_cast (执行 dynamic_cast<>() 任何容器的条目)iterator_transform_traits_map_any_second (对 map 条目的 any_cast<>() 执行 second )当然,这遗漏了很多有用的东西(因为还没有人需要它们),而且根本无法扩展。我只是负责编写一个迭代器来取消引用 map 条目的 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以及所有那些花哨的东西。
最佳答案
给你:
#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 的小元编程操作,我希望元函数名称足够明确,请随时提问问题mpl 序列作为模板参数,因为您无权访问 C++11 和可变参数模板。关于c++ - 为 boost 的变换迭代器寻找复合特征模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21452523/
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我