Raider wrote:
The const-ness of the proxy itself shouldn't matter. Only the const-ness of the proxied object should matter.
I want const_iterator to be dereferencable to const object and iterator to non-cont object. Like this:
class vec { public: vec(sv& v = global) : v_(v) {} typedef sv::iterator 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_; };
It's not wrong to want that. But it is for important safety reasons that BOOST_FOREACH treats copies of containers as const. In some of the examples you've shown so far, you're trying to proxy a temporary object so you can modify it. That's never going to work. Like this:
for (xxx::iterator it(GetVector().begin(), end(GetVector().end()); it != end; ++it) { modify(*it); }
That's not even valid C++. But even if it were and GetVector() returns a temporary object or a proxy to a temporary object, the vector will be destroyed before you can iterate it. The interface I chose preserves object lifetimes and prevents inadvertent mutation of temporary objects. Weakening its guarantees is a bad idea. If you want the proxy to offer either a const or mutable interface *and* you want your proxy to work with BOOST_FOREACH, you should base it on the const-ness or mutability of the object being proxied, not the constness of the proxy itself. Consider: template<class Range> struct proxy { typedef typename range_result_iterator<Range>::type iterator; typedef typename range_result_iterator<Range>::type const_iterator; iterator begin() const { return boost::begin(rng_); } iterator end() const { return boost::end(rng_); } // etc ... Range &rng_; }; Now, you can have const and mutable proxied objects like: // ok, a mutable proxy proxy< std::vector<int> > p1; // ok, still a mutable proxy proxy< std::vector<int> > const p2; // ok, a const proxy proxy< std::vector<int> const > p3; // still a const proxy proxy< std::vector<int> const > const p4; You can easily write a helper function to create the proxy object for you that has the correct const behavior.
This allows me make no difference does GetVector() return `vec' type (proxy) or `sv&' (reference to the real container):
As does the above.
Now I found some unsteady way: #define BOOST_FOREACH_NO_RVALUE_DETECTION makes my code compile. I'll try to dig in this direction.
Don't do it. Bad things can happen if you use rvalues after you've turned off foreach's rvalue detection. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com