简体   繁体   English

C ++设置迭代器错误:“ operator + =”不匹配

[英]C++ set iterator error: no match for ‘operator+=’

I am trying to iterate over a set of objects and create a comma-separated string of their names. 我正在尝试遍历一组对象并创建它们名称的逗号分隔字符串。 The commented-out part of the code is supposed to add a comma only if it is not the last one in the set, but it generates the following error: 仅在代码注释掉的部分不是集合中的最后一个时,才应添加逗号,但是会产生以下错误:

error: no match for 'operator+=' (operand types are 'std::_Rb_tree_const_iterator' and 'long int') _M_current += -__n; 错误:与'operator + ='不匹配(操作数类型为'std :: _ Rb_tree_const_iterator'和'long int')_M_current + = -__ n;

It works fine if I use a vector instead of a set. 如果我使用向量而不是集合,则效果很好。 What am I doing wrong? 我究竟做错了什么?

std::string paramList = "";
std::set<Param>::iterator end = params.end();
for (std::set<Param>::iterator it = params.begin(); it != end; ++it) {
  paramList += (*it).name;
  /*if (it != end -1) {
    paramList += ",";
  }*/
}

Only certain categories of iterator allow you to directly perform arbitrary arithmetic, like end-1 . 仅某些迭代器类别允许您直接执行任意算术,例如end-1

The iterator of a set permits going forwards and backwards one step at a time, using it++ and it-- . 集合的迭代器允许每次使用it++it--向前和向后前进一个步骤。 It is true that it - 1 still only traverses one step, but the rule is more general (the language doesn't know that the integer you're providing is just 1 and has no reason to make a special case compared to, say, 42 ). 的确如此it - 1仍然只遍历一个步骤,但是规则却更笼统(语言不知道您提供的整数仅为1it - 1相比,没有理由做特殊情况) 42 )。

It is possible to use std::next / std::prev to get this behaviour. 可以使用std::next / std::prev获得此行为。 This is deliberately more verbose, in order to discourage you from arbitrary arithmetic on the iterator, which is more costly for this kind of iterator than it would be for a simple array-like thing such as a vector. 为了使您避免使用迭代器上的任意算术,这故意更冗长,与使用简单的类似数组的对象(例如矢量)相比,这种迭代器的开销更大。

In this case, std::prev(end) will work for you, and be reasonably idiomatic. 在这种情况下, std::prev(end)将为您工作,并且是习惯用法。

But, if you find yourself writing something like std::next(it, 42) , you probably want to consider improving your algorithm, or using a different container. 但是,如果您发现自己编写了类似std::next(it, 42) ,则可能要考虑改进算法或使用其他容器。

Again, the purpose of this restriction is to encourage exactly that thinking. 同样,这种限制的目的是鼓励这种思维。

Another way to write your algorithm might be: 编写算法的另一种方法可能是:

std::string paramList;
std::set<Param>::iterator begin = params.begin(), end = params.end();
for (std::set<Param>::iterator it = begin; it != end; ++it) {
  if (it != begin)
    paramList += ",";

  paramList += (*it).name;
}

Notice how I've flipped the logic to avoid the need to do any arithmetic at all. 请注意,我是如何翻转逻辑的,以免完全不需要做任何算术运算。

I actually usually use a bool flag for this (when my paramList is a stringstream) or just always append a , then shrink paramList by one later (when it's a string) if params was non-empty. 实际上,我通常为此使用bool标志(当我的paramList是stringstream时),或者总是总是附加a ,然后如果params非空,则将paramList缩小一个(当它是字符串时)。

end -1

This part is causing the problem. 这是造成问题的原因。 std::set only has Bidirectional iterators , so it only accepts operator ++ and operator -- on it. std::set仅具有双向迭代器 ,因此它仅接受operator ++operator --

You should use std::prev form <iterator> header instead: 您应该使用std::prev form <iterator>标头代替:

if (it != std::prev(end))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM