
MB wrote:
Errata:
But I think about the case that my ranges which are customized as 'cheap_copy' becomes base classes of anyone else.
replaces:
>But I think about the case that my ranges which are customized as 'cheap_copy' >are derived from anyone else.
English is as difficult as C++ :-)
Now that 'has_cheap_copy' becomes one of the requirements of Range-concepts, doesn't it?
No. Boost.Range defines the range concept, and FOREACH works correctly with any type that satisfies that concept. has_cheap_copy is nothing more than an optimization hint to the BOOST_FOREACH macro. It is not required and it doesn't change the meaning of anything.
But the hint expands to the derived classes and the derived classes "must" customize 'has_cheap_copy'.
I agree that's not good. I've reimplemented the has_cheap_copy customization point again. See below.
In general, do we have the safe way of telling whether or not a type is cheap to copy without metafunctions?
No.
Is it portability-issue the reason why you avoid metafunctions?
You mean, why isn't there a has_cheap_copy<T> trait? I had originally wanted the cheap_copy optimization to automatically apply to derived types, which is the reason for the particular form of the customization point. I no longer think that's a good idea, so I can now add a has_cheap_copy<> trait, however ... ... on compilers without partial template specialization, there isn't a good way of saying that for all types T, boost::iterator_range<T> is cheap to copy. So the free function template is still the way to go on those compilers. Here is the new-and-improved(-and-please-god-let-this-be-the-last) way to optimize FOREACH for cheap-to-copy types: - For a user-defined range type Foo that is cheap to copy, you should specialize has_cheap_copy<> in the boost::foreach namespace, as: namespace boost { namespace foreach { template<> struct has_cheap_copy<Foo> : mpl::true_ {}; }} - For maximum portability, you could achieve the same effect by overloaded boost_foreach_has_cheap_copy() at global scope like this: inline boost::mpl::true_ * boost_foreach_has_cheap_copy(Foo *&, boost::foreach::tag) { return 0; } (The slightly strange Foo *& type prevents this overload from being selected for types derived from Foo.) By default FOREACH defines overloads to recognize std::pair<T,T>, iterator_range<T> and sub_range<T> as cheap-to-copy, but NOT types derived from them. I hope this is satisfactory. -- Eric Niebler Boost Consulting www.boost-consulting.com