C++ 携带方便的好方法”;在条件表达式中赋值“;没有警告(或pragmas)?

C++ 携带方便的好方法”;在条件表达式中赋值“;没有警告(或pragmas)?,c++,conditional,variable-assignment,C++,Conditional,Variable Assignment,我有一段代码如下: bool finished = false; size_t offset = 0; for (Iter i = items.begin(); i != items.end() || (finished = !finished); finished ? i : ++i, ++offset) { do_some_work(); if (some_condition(other_collection[offset]))

我有一段代码如下:

bool finished = false;
size_t offset = 0;
for (Iter i = items.begin();
          i != items.end() || (finished = !finished);
          finished ? i : ++i, ++offset)
{
    do_some_work();
    if (some_condition(other_collection[offset]))
    {
        i = items.insert(i, new_value());
        do_more_work();
        if (blah) { continue; }
    }
    do_more_work();
}
for( auto it : iterators( sequence, include_end ) ) {
  // code
}
目标是为所有迭代器执行主体,包括
end()

我得到“条件表达式中的赋值”,如VisualC++ + .p/>编译器警告。 避免这些警告的最简单方法是什么? 我不想关闭它们(它们很有用),也不想插入

#pragma
s(它们不能在编译器之间移植)。
我只想写一些简短的东西,告诉典型的编译器,“是的,我打算在这里赋值”


我发现的最简单的解决方案是创建一个函数(例如,
分配
)并调用它,但我想知道是否有任何方法也可以避免仅为此定义一个新函数。

您可以尝试使用
提示您打算将
(finished=!finished)
视为布尔值(它是两个
顺序一元数,并将0转换为0,将其他所有内容转换为1):


使用好的ol'
作为i

#include <vector>
#include <iostream>


int main() {
    std::vector<int> v = { 1, 5, 23, 2, 44 };
    auto iter = v.begin();
    for (std::size_t i = 0; i != v.size() + 1; ++i, ++iter) {
        if(iter == v.end()) {
            std::cout << "END!" << std::endl;
        }
        else {
            std::cout << *iter << std::endl;
        }
    }
}

如果要执行
结束
的循环,即使它等于
开始
,循环始终至少执行一次

在这种情况下,可能最容易将其编写为
do
/
while
循环,因此它仅在执行循环体后测试条件:

bool continuing;
i = begin;
do { 
    whatever();
} while ((continuing = (i != end)) && (++i, continuing));

丑陋终止条件根据end测试迭代器的当前值,然后在(且仅当)需要执行另一个迭代时(然后使用原始比较中的值继续/中断循环)为下一个迭代增加迭代器,您没有迭代容器的内容。而是在容器的有效迭代器上进行迭代

因此,一种方法是明确这一点

创建所述迭代器的序列,其中
end
元素超过序列中最后一个迭代器的-
end

因为我疯了,如果我必须解决这个问题,我会编写一个函数
迭代器
,当给定一个
序列
(一个
for(:)
循环工作的对象)时,它会生成迭代器的
序列
,而不是底层类型的序列

它将采用一个
enum
参数,说明它是否包含-
end
迭代器。它将默认为独占

您可以这样使用它:

bool finished = false;
size_t offset = 0;
for (Iter i = items.begin();
          i != items.end() || (finished = !finished);
          finished ? i : ++i, ++offset)
{
    do_some_work();
    if (some_condition(other_collection[offset]))
    {
        i = items.insert(i, new_value());
        do_more_work();
        if (blah) { continue; }
    }
    do_more_work();
}
for( auto it : iterators( sequence, include_end ) ) {
  // code
}
编写该函数的工作不会很琐碎,但它会使使用点的循环看起来非常干净

以理智的方式编写这篇文章需要使用
boost
迭代器库。稍微不那么明智的做法是重新实现一段
boost
迭代器库,要么逐字逐句,要么手工编写,然后使用它。如果不抄袭boost的精神或文本来编写它,那将是一个坏主意

template<typename iterator>
struct iterator_iterator: boost::iterator_facade<
  iterator_iterator<iterator>, iterator,
  typename std::iterator_traits<iterator>::iterator_category,
  iterator const&,
  typename std::iterator_traits<iterator>::difference_type
>:{
  // sufficient state:
  iterator current;
  iterator src_end;
  bool past_end_iterator;
  // now, implement the core operations.  Note that
  // random advance has to be careful, because we cannot advance
  // current beyond src_end.  Note we should implement every one
  // of the methods in the requirements (including advance), but
  // only the ones that the underlying iterator's category requires
  // should be called and hence instantiated.
  iterator dereference() const { return current; }
  bool equal( iterator_iterator<iterator> other ) const {
    if (past_end_iterator || other.past_end_iterator)
      return past_end_iterator && other.past_end_iterator;
    return current == other.current;
  }
  void increment() {
    if (current == src_end) {
      past_end_iterator = true;
    } else {
      ++current;
    }
  }
  void decrement() {
    if (past_end_iterator) {
      past_end_iterator = false;
    } else {
      --current;
    }
  }
  void advance( std::ptrdiff_t n ) {
    if (n==0)
      return;
    if (n==1) {
      increment();
    } else if (n==-1) {
      decrement();
    }
    if ((n>0) && ( current+(n-1) == src_end ) {
      current = src_end;
      past_end_iterator = true;
    } else if ((n<0) && past_end_iterator) {
      past_end_iterator = false;
      ++n;
      current = src_end + n;
    } else {
      current += n;
    }
  }
  typename std::iterator_traits<iterator>::difference_type distance_to(
    iterator_iterator<iterator> other
  ) const {
    if (past_end_iterator || other.past_end_iterator) {
      if (past_end_iterator && other.past_end_iterator) {
        return 0;
      using std::distance;
      auto retval = distance( current, other.current );
      if (past_end_iterator)
        return retval-1;
      else
        return retval+1;
    }
  }
};
模板
结构迭代器迭代器:boost::迭代器<
迭代器迭代器,迭代器,
typename std::iterator_traits::iterator_category,
迭代器常量&,
类型名称std::迭代器特征::差异类型
>:{
//充分状态:
迭代器电流;
迭代器src_end;
布尔过去迭代器;
//现在,实现核心操作
//随机前进必须小心,因为我们不能前进
//电流超出src_端。注意,我们应该实现每一个
//要求中的方法(包括预付款),但
//只有底层迭代器的类别需要的
//应该被调用并因此被实例化。
迭代器取消引用()常量{return current;}
布尔相等(迭代器\迭代器其他)常量{
if(过去的迭代器| |其他.过去的迭代器)
返回过去的迭代器&&other.pass\u end\u迭代器;
返回电流==其他电流;
}
无效增量(){
如果(当前==src\U端){
过去\结束\迭代器=真;
}否则{
++电流;
}
}
无效减量{
if(经过\u结束\u迭代器){
过去\结束\迭代器=false;
}否则{
--电流;
}
}
作废预付款(std::ptrdiff\n){
如果(n==0)
返回;
如果(n==1){
增量();
}else if(n==-1){
减量();
}
如果((n>0)和&(当前+(n-1)=src_end){
电流=src_端;
过去\结束\迭代器=真;

}否则如果((不要紧,我自己找到了解决办法

for (Iter i = items.begin();
          i != items.end() || (finished = !finished, finished);
          finished ? i : ++i, ++offset)
{
    // ...
}

在使用调试迭代器时,有些实现可以检测到问题。@R.MartinhoFernandes说了些什么。@Mehrdad:我相信(以一点丑陋为代价)这是正确的。+1是的,谢谢。我想我最终也找到了一个更好的解决方案,我会在一秒钟内发布它。只有当你知道你必须从多少项开始时才有效…+1,因为它适用于大多数情况,但我希望找到一个不会施加不必要限制的解决方案。@Mehrdad我知道,我有一些东西可以编辑以解决这个问题。:)@mehrdad std::距离为awesome@A.H.如果它被调用在非随机访问(O(n))迭代器上!你的循环已经执行O(n)步骤。(但是如果你真的想要一个反对意见,想想输入迭代器)它似乎不工作Visual C++ 2013不幸的是,不确定其他版本。(+1,用于在回答问题的同时提高代码的可读性。@Mehrdad在使用时更具可读性——但要做到这一点需要大量的样板文件!是的,这就是为什么我还没有走这条路哈哈。我很高兴你找到了一个你可以接受的解决方案,但伙计,我希望没有其他人能够坚持这一点代码:)这里几乎所有的其他答案都比这个oneNote好,因为你的
++i
与你的
i=items冲突。插入(…
)在某种程度上——如果你不非常小心,你将跳过迭代器的访问。@Yakk:是的,这只是一个例子……不要