Boost logo

Boost Users :

From: Eric Niebler (eric_at_[hidden])
Date: 2007-07-23 15:14:04


Raider wrote:
>>> It doen't compiles (MCVC 8.0) - it looks like
>>> boost_foreach_is_lightweight_proxy is ignored. What's wrong?
>> It's not being ignored --- std::vector is simply not a lightweight
>> proxy. You're lying to BOOST_FOREACH, and it's found you out. :-) The
>> docs say this about lightweight proxy types:
>>
>>> A pair of iterators is an example of a lightweight proxy. It does not store the values of the sequence; rather, it stores iterators to them. This means that iterating over a copy of the proxy object will give the same results as using the object itself.
>> Iterating over a copy of a std::vector isn't the same thing as as
>> iterating over the original vector because the elements have been
>> copied. When BOOST_FOREACH has to make a copy of a sequence (and it
>> always copies lightweight proxies), it treats the copy as const because
>> it's a temporary object. That's fine for *real* proxies because the
>> const-ness of the proxy doesn't affect the constness of the referred-to
>> elements.
>>
>> I think BOOST_FOREACH is doing the right thing here.
>
> It's not about std::vector, it's about
> boost_foreach_is_lightweight_proxy. I used std::vector only to make
> example code small. If you think std::vector make sence, you can change
> "typedef std::vector<std::string> vec;" line by the following:
>
> typedef vector<string> sv;
> sv global;
> class vec
> {
> public:
> vec(sv& v = global) : v_(v) {}
> typedef sv::iterator iterator;
> typedef sv::const_iterator const_iterator;
> iterator begin() { return v_.begin(); }
> iterator end() { return v_.end(); }
> const_iterator begin() const { return v_.begin(); }
> const_iterator end() const { return v_.end(); }
> void push_back(const string& s) { v_.push_back(s); }
> private:
> sv& v_;
> };
>
> It's a *real* _lightweight_ proxy, but still getting a compiler error!

Better, but you have proxied a non-const vector, and you're presenting a
const interface. Try this:

   class vec
   {
   public:
        vec(sv& v = global) : v_(v) {}
        typedef sv::iterator iterator;
        typedef sv::iterator const_iterator;
        typedef sv::const_iterator const_iterator;
        iterator begin() const { return v_.begin(); }
        iterator end() const { return v_.end(); }
        void push_back(const string& s) const { v_.push_back(s); }
   private:
        sv& v_;
   };

The const-ness of the proxy itself shouldn't matter. Only the const-ness
of the proxied object should matter.

HTH,

-- 
Eric Niebler
Boost Consulting
www.boost-consulting.com
The Astoria Seminar ==> http://www.astoriaseminar.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net