我管理一个对象集合(Collection of Real 作为一个简单的例子)。然后我在我的集合上定义了迭代器。这意味着:iterator、const_iterator、reverse_iterator 和 const_reverse_iterator。在这个例子中,我只关注iterator和const_iterator,其他两个非常相似。
之后,我想在我的集合上定义一个过滤器,它根据特定条件保留或不保留元素。例如,仅保留具有正值的 Real 实例。我还想只对保留的元素迭代我的集合。
对于这个例子,我在集合中的对象非常简单。目标只是拥有一个对象而不是原生类型:
struct Real
{
public:
double r;
};
然后我定义我的集合而不必知道里面的真实容器:
class Collection
{
public:
typedef std::vector<Real>::iterator iterator;
typedef std::vector<Real>::const_iterator const_iterator;
private:
std::vector<Real> data;
public:
Collection() : data() {}
Collection(unsigned long int n) : data(n) {}
Collection(unsigned long int n, const Real& x) : data(n,x) {}
Collection::iterator begin() { return this->data.begin(); }
Collection::iterator end() { return this->data.end(); }
Collection::const_iterator begin() const { return this->data.begin(); }
Collection::const_iterator end() const { return this->data.end(); }
};
在这个简单的例子中效果很好:
int main()
{
Collection c(5);
double k = 1.0;
for(Collection::iterator it = c.begin(); it != c.end(); ++it)
{
it->r = k;
k *= -2.0;
}
std::cout << "print c with Collection::iterator" << std::endl;
for(Collection::iterator it = c.begin(); it != c.end(); ++it)
std::cout << it->r << std::endl;
std::cout << "print c with Collection::const_iterator" << std::endl;
for(Collection::const_iterator it = c.begin(); it != c.end(); ++it)
std::cout << it->r << std::endl;
return 0;
}
这个程序写出了预期的输出:
print with Collection::iterator
1
-2
4
-8
16
print with Collection::const_iterator
1
-2
4
-8
16
现在我想创建一个抽象过滤器,具有指向集合的引用或指针、迭代器以及通过过滤器接受值的抽象函数。对于第一步,我只编写了没有迭代器的类:
class CollectionFilter
{
private:
Collection& col;
public:
CollectionFilter(Collection& c) : col(c) {}
virtual ~CollectionFilter() {}
Collection& collection() { return this->col; }
iterator begin() { /* todo */ }
iterator end() { /* todo */ }
const_iterator begin() const { /* todo */ }
const_iterator end() const { /* todo */ }
virtual bool accept(const Real& x) const = 0;
};
然后,很容易创建一个实现特定条件的新过滤器:
class CollectionFilterPositive : public CollectionFilter
{
public:
CollectionFilterPositive(Collection& c) : CollectionFilter(c) {}
virtual ~CollectionFilterPositive() {}
virtual bool accept(const Real& x) const { return x.r >= 0.0; }
};
在过滤器中实现迭代器之前,我有一些评论/问题。
Collection&,那么,是否真的需要 begin() const 和 end() const 函数?如果是,为什么?const Collection& 上应用过滤器,但这显然是我的目标所必需的。这样做的好方法是什么?我是否必须将 CollectionFilter 类复制到具有非常相似代码的 CollectionFilterConst 类?此外,对于必须从两个相似类继承的用户来说,此解决方案非常令人困惑。然后,让我们来看看迭代器的实现。对于这个例子,我只写了 iterator 而没有写 const_iterator。我将其添加到我的类(class)中:
class CollectionFilter
{
public:
class iterator
{
private:
CollectionFilter* filter;
Collection::iterator iter;
public:
iterator(CollectionFilter* f, Collection::iterator i) : filter(f), iter(i) {}
iterator(const iterator& i) : filter(i.filter), iter(i.iter) {}
iterator& operator = (const iterator& i) { this->filter = i.filter; this->iter = i.iter; return *this; }
iterator& operator ++ ()
{
if(this->iter != this->filter->collection().end())
{
do
{
++this->iter;
} while(this->iter != this->filter->collection().end() && !this->filter->accept(*this->iter));
}
}
iterator operator ++ (int) { /* similar */ }
Real& operator * () { return *this->iter; }
Collection::iterator operator -> () { return this->iter; }
bool operator == (const iterator& i) const { return this->iter == i.iter; }
bool operator != (const iterator& i) const { return this->iter != i.iter; }
};
public:
iterator begin()
{
Collection::iterator it = this->col.begin();
if(!this->accept(*it)) ++it;
return CollectionFilter::iterator(this,it);
}
iterator end()
{
Collection::iterator it = this->col.end();
return CollectionFilter::iterator(this,it);
}
};
这在这个简单的例子中也很有效
int main()
{
Collection c(5);
double k = 1.0;
for(Collection::iterator it = c.begin(); it != c.end(); ++it)
{
it->r = k;
k *= -2.0;
}
std::cout << "print c with CollectionFilterPositive::iterator" << std::endl;
CollectionFilterPositive fc(c);
for(CollectionFilterPositive::iterator it = fc.begin(); it != fc.end(); ++it)
std::cout << it->r << std::endl;
return 0;
}
给出预期的输出:
print with CollectionFilterPositive::iterator
1
4
16
再次,一些问题:
CollectionFilter::iterator 的代码来实现 CollectionFilter::const_iterator,只需稍作修改。有没有办法避免这段代码的重复(写了 8 次,如果我算上重复的类 CollectionFilterConst 和反向迭代器)?提前致谢!
最佳答案
- This filter works on a non-
constCollection&, then, are thebegin() constandend() constfunction really required ? And if yes, why ?- I can't apply the filter on a
const Collection&, but it's clearly required for my goal. What could be a good way to do that ? Have I to duplicate theclass CollectionFilterto aclass CollectionFilterConstwith a very similar code ? Moreover this solution is quite confusing for the user having to inherit from two similar classes.
这些问题非常相关。基本上,将过滤限制为非常量 Collection 是否有意义? ?这对我来说意义不大。我们没有修改 CollectionFilter对象,只有底层 Collection对象(可能),以及 Filter 的功能与 Collection 是否无关是const .将所有这些放在一起,它需要一个模板:
template <typename C>
class Filter {
static_assert(std::is_same<
std::decay_t<C>,
Collection
>::value, "Can only filter a Collection.");
using collection_iterator = decltype(std::declval<C&>().begin());
C& collection_;
public:
Filter(C& collection) : collection_(collection) { }
struct iterator {
/* TODO, use collection_iterator */
};
iterator begin() const { /* TODO */ };
iterator end() const { /* TODO */ };
};
这边,Filter<Collection>::collection_iterator是Collection::iterator和 Filter<const Collection>::collection_iterator是Collection::const_iterator .你不能做 Filter<std::vector<int>> .
这也回答了您的其他问题 - 这是一个 const - 过滤任何集合的正确、非重复方法。
为了避免额外的输入,您还可以创建一个构建器函数:
template <typename <typename> class F, typename C>
F<C> makeFilter(C& collection) {
return F<C>(collection);
}
auto filter = makeFilter<CollectionFilterPositive>(some_collection);
const filter 的迭代器的 -ness将取决于 const -性 some_collection .
我也会调查 Boost.IteratorFacade写作 Filter::iterator ,它将为您节省一些时间和一些麻烦。
关于c++ - 自制迭代器的常量正确性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30711374/
在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到rubygems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc
我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参
我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西: