c++ - Forward iterator/random acces iterator and `operator*` over temporary iterators -
is this:
auto& ref1 = *it++; ref1 = expression; // (1)
one of required semantics of forward iterator? , random access iterator?
auto& ref1 = it[3]; ref1 = expression; // (2)
according cppreference
, forward iterator required to:
// return reference, equals (const) value_type & *it++ === value_type&
and random access iterator:
it[n] === *(it + n)
which same situation, means in both situations dereferencing temporary (the iterator). in case, iterator stores copy index allows access container doesn't provide direct access stored elements, through index.
that works fine:
*it++ = value;
since temporary copy of it
has sentence scope.
but in case:
type& val = *it++; val = 3;
we undefined behaviour, since copy destroyed in second line.
in situation, have qmodelindex
wrapper data/save from/to qabstractitemmodel
. model gives copies of qvariant
s stored on model.
my wrapper class (the value_type
operator=
overloaded) saves instance of qmodelindex
(to manipulate model), , iterator instance of wrapper. so, if iterator destroyed, wrapper , index too.
i think can solve both problems far lines (1)
, (2)
don't need supported.
note: implementation more or less (simplified):
// value type struct index { qmodelindex qidx; index& operator=(qvariant const& val) { if (qidx.isvalid()) qidx.model()->setdata(qidx, val); return *this; } }; // private class actually. "movements" cannot done // on value type because cause, in functions // returning references value type, increase chaos. // so, make index points different model items using // class. struct index_manipulator { qmodelindex& qidx; void move(int rows, int cols) { if (qidx.isvalid()) qidx = qidx.model()->index(qidx.row() + rows, qidx.column() + cols); } }; struct index_safe_ref { mutable index idx; operator index&() const { return idx; } }; struct my_row_it { index idx; index_manipulator manip = {idx.qidx}; my_row_it(qabstractitemmodel* m, int col) : idx(m ? m->index(0, col) : qmodelindex()) {} index& operator*() const { return idx; } my_row_it operator++(int) const { auto copy = it; manip.move(1, 0); return copy; } index_safe_ref my_row_it::operator[](difference_type n) const { auto = + n; // operator+ on there. return { it.idx }; } };
a stashing iterator (that is, iterator returns reference within itself) never valid forward iterator.
iterators in general must copyconstructible
([iterator.iterators]/2.1, requires, among other things, copy of iterator equivalent original. follows forward iterator , copy must compare equal, , [forward.iterators]/6 requires that 2 equal dereferenceable iterators a
, b
, *a
, *b
must bound same object, cannot satisfied stashing iterators.
if need ignore requirement, suggest ignoring 1 says reference
must actual reference type, turning stashing iterator proxy iterator. there's established practice in standard library (vector<bool>::iterator
) , breakage loud compile-time error, rather silent runtime mischief.
Comments
Post a Comment