
Eric Niebler wrote:
MB wrote:
Hi,
Under VC++7.1, I was surprised that a class derived from 'boost::iterator_range' was almost copied by BOOST_FOREACH. ('boost::noncopyable' works!)
I think such a range that is noncopyable but derived from iterator_range is valid, isn't it ...? I think it could be dangerous if users can't find cheap_copy-customization.
Hrm, right. I feel some explanation is in order. The support for const rvalue detection is not without runtime cost, and it's all to avoid needless copying of expensive range-like objects such as STL containers. But when the range is something small like a boost::iterator_range, jumping through hoops of fire to avoid copying one is just silly. Hence the cheap_copy hack: BOOST_FOREACH has an optimized code path for types it knows (or believes to be) cheap to copy.
You have run afoul of the cheap_copy optimization. Rightly or wrongly, it assumes types derived from boost::iterator_range are cheap to copy, but that's not the case for you. There are two possible fixes, and they both involve documenting the cheap_copy customization point (and probably fixing it to use ADL like boost::begin()):
1) By default, only apply the optimization to boost:iterator_range and its ilk, NOT to types derived from them.
2) Leave the code as it is, and force people in your situation to use the cheap_copy customization point to disable the optimization.
I currently lean toward (1).
I will vote for (2) only because almost all my ranges are cheap-copyable and derived from iterator_range :-) But I don't know for sure. I learnt from books to vote for (1). Regards, MB http://p-stade.sourceforge.net/