Topic: Simple question ?


Author: James Kuyper <kuyper@wizard.net>
Date: 1998/04/09
Raw View
Alex Martelli wrote:
>
> Mark.Huiskes@ZTW.WK.WAU.NL (Mark Huiskes) writes:
>
> >Hi, I have a very simple question, I think.
> >I'm using a set of objects and now I want to perform a (non-const)
> >memberfunction on each of the objects in the set, so I used the following
>
> An std::set<T>::iterator, dereferenced, returns a const T&; this is
> deemed necessary because, otherwise, a generic method called on such
> a dereferenced iterator might alter the item's proper order within
> the set, i.e. invalidate the set's whole structure.  Therefore, what
> you want cannot be done without a const_cast<>, or some other trick
> such as, supposing that you don't actually care about the ordering
> of the elements in the set:

That makes perfect sense; now where does it say that in the standard?
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Mark.Huiskes@ZTW.WK.WAU.NL (Mark Huiskes)
Date: 1998/04/06
Raw View
Hi, I have a very simple question, I think.
I'm using a set of objects and now I want to perform a (non-const)
memberfunction on each of the objects in the set, so I used the following
lines of code:

TgStateSet::iterator gStateSetI=pState.gStateSet.begin();
for (gStateSetI=pState.gStateSet.begin();
 gStateSetI!=pState.gStateSet.end();gStateSetI++) {
       (*gStateSetI).Map(eState,Pars);
       (*gStateSetI).iState.Map(eState,Pars);
}

I guess there's something wrong with this since my compiler says that the
dereferenced iterator (*gStateSetI) returns a constant object !! The
object pState enters the function in which I use this code through a non-
const reference (this is the function header: )

int Compute(TpState& pState, TeState& eState,
 double* Pars, const int& tMin, const int& tMax) {

and nowhere in my original class definition do I mention anything about
it being constant. Could somebody help me with this ?
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: martelli@cadlab.it (Alex Martelli)
Date: 1998/04/08
Raw View
Mark.Huiskes@ZTW.WK.WAU.NL (Mark Huiskes) writes:

>Hi, I have a very simple question, I think.
>I'm using a set of objects and now I want to perform a (non-const)
>memberfunction on each of the objects in the set, so I used the following

An std::set<T>::iterator, dereferenced, returns a const T&; this is
deemed necessary because, otherwise, a generic method called on such
a dereferenced iterator might alter the item's proper order within
the set, i.e. invalidate the set's whole structure.  Therefore, what
you want cannot be done without a const_cast<>, or some other trick
such as, supposing that you don't actually care about the ordering
of the elements in the set:

template <typename T>
class wrapper {
    const size_t prognum;
    static size_t id;
    mutable T t;
public:
    wrapper(T t): t(t), prognum(++id) {}
    wrapper(const wrapper& w): t(w.t), prognum(++id) {}
    wrapper& operator=(const wrapper& w) {
 t = w.t;
 return *this;
    }
    operator T&() const { return t; }
    T& unwrap() const { return t; }
    bool operator<(const wrapper& w) const { return prognum<w.prognum; }
};
template <typename T> size_t wrapper<T>::id;

std::set<wrapper<whatever> > hset;


*Now* you can iterate through hset as in:

    for(std::set<wrapper<whatever> >::iterator i = hset.begin();
 i!=hset.end(); ++i)
     i->unwrap().any_method();

secure in the knowledge that the any_method(), while possibly
modifying the "whatever" wrapped object, will not affect hset's
structure, since the less<wrapper<whatever> > only depends on
the wrapper objects' immutable prognum members.

This is only an outline, of course -- you'll want to tailor your
wrapper templates, or custom classes, to your actual needs (e.g.
a wrapper might hold a T by-reference rather than by-value, etc
etc).  As long as the non-const methods you want to call on the
objects in the set will *definitely* not alter their comparison
orders, you might even have wrapper<T>::operator< delegate to
T::operator<. of course (under your sole responsibility... be
sure to comment such assumptions in detail, for maintainers'
sanity's sake!-).

The situation is more ticklish if you DO want to call, on objects
within a set, methods that MIGHT in fact change their sorting
order.  If that is the case, then you may have to remove objects
from the set (to a list or whatever), iterate on the auxiliary
container, then rebuild the set from scratch.  Designing a sorted
container which self-maintains its structure under arbitrary mods
to the contained elements is not trivial, and the Standard C++
Library sorted containers do not have this goal (which would make
operation substantially slower for all cases where such a goal is
not of interest).


Alex
--
 ____    Alex Martelli, Bologna, Italia -- email: alex@magenta.com
 \SM/___                                 http://magenta.com/~alex
  \/\bi/     You never know what is enough unless you know what
     \/          is more than enough.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]