Meh*_*dad -1 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]))
{
i = items.insert(i, new_value());
do_more_work();
if (blah) { continue; }
}
do_more_work();
}
Run Code Online (Sandbox Code Playgroud)
目标是为所有迭代器执行主体,包括end().
我从Visual C++等编译器获得"条件表达式中的赋值"警告.
我不想关闭它们(它们很有帮助)而且我不想插入#pragmas(它们在编译器之间不可移植).
我只想写一些简短的东西来告诉典型的编译器,"是的,我打算在这里分配".
我发现的最简单的解决方案是创建一个函数(例如assign)并调用它,但我想知道是否有任何方法也可以避免为此定义一个新函数.
使用好的'' for 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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新:为了回应你的评论,我修改了代码使用std::distance,让你只使用迭代器而不直接知道迭代器范围的大小.
#include <vector>
#include <iostream>
template<typename IterType>
void print(IterType iter /* begin */, IterType end) {
auto size = std::distance(iter, end);
for (decltype(size) i = 0; i != size + 1; ++i, ++iter) {
if(iter == end) {
std::cout << "END!" << std::endl;
}
else {
std::cout << *iter << std::endl;
}
}
}
int main() {
std::vector<int> v = { 1, 5, 23, 2, 44 };
print(v.begin(), v.end());
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您不会迭代容器的内容.相反,您正在迭代容器的有效迭代器.
因此,一种方法是明确这一点.
创建一个所述迭代器的序列,其end元素是end序列的最后一个迭代器的一个元素.
因为我疯了,如果我必须解决这个问题,我会编写一个函数iterators,当给定一个sequence(一个for( : )循环工作的对象)时,会生成一个sequence迭代器而不是底层类型的序列.
它需要一个enum论证,说它是否包含了end迭代器.它将默认为独占.
你会这样使用它:
for( auto it : iterators( sequence, include_end ) ) {
// code
}
Run Code Online (Sandbox Code Playgroud)
编写该函数的工作不会是微不足道的,但它会使得使用点的循环看起来非常干净.
以理智的方式编写它将涉及使用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;
}
}
};
Run Code Online (Sandbox Code Playgroud)
或类似的东西.(编译没有,只是写的)你最好把你对开始/结束迭代器,以及创建一对开始/结束迭代器迭代器,或者开始/结束过去迭代器迭代器,这取决于您是否要包括结束迭代在迭代器的迭代中.
我怀疑上面的CRTP是堆栈溢出代码中迭代器一词有用的最高密度:在5行代码中使用迭代器.