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:是的,这只是一个例子……不要