
On Fri, Apr 30, 2010 at 3:37 AM, Samuel Debionne<debionne@hydrowide.com> wrote:
Hello all, I'm scratching my head about the correct way to use transform_iterator with bind and mem_fn. In brief, bind and mem_fn return object functions that are not Default Constructible, which means that, when used to construct a transform_iterator, the resulting transform_iterator is not even a Trivial Iterator.
Most of the case, it's not a problem because the transform_iterator is never default constructed... until some libs that do concept checking on their template parameters are used. See the following code for exemple :
Right, mem_fn_t is not DefaultConstructible, so a transform_iterator with mem_fn_t does not model ForwardTraversalIterator. Likewise with the return type of bind, which c++0x requires to be MoveConstructible (and CopyConstructible when it's args are) but not DefaultConstructible. In your specific example, however, you can still build a valid ForwardTraversalIterator by using boost::function to erase the return type of mem_fn. The same should work with bind.
check(make_transform_iterator( foo_vec.begin(), function<size_t(foo&)>(mem_fn(&foo::get_id))));
check(make_transform_iterator( foo_vec.begin(), function<size_t(foo&)>(mem_fn(&foo::id_))));
Daniel Walker
Daniel, thank you for your solution. But doesn't type erasure avoid some optimisations to take place (inlining) ? That could be a problem since the function is called each time the iterator is deferred. I just did some benchmarking that consists in accumulating a large range of foo id. Here are the results with vc10 : Boost.Function vs Hand Written : 9 time slower Boost.MemFn vs Hand Written : 3.7 time slower Boost.Function vs Boost.MemFn : 1.6 time slower Anyway, in my opinion, using bind/mem_fn/lambda with transform_iterator is a common use case. That would be great to have an option to add a default constructor in those libs... or is it to risky ? Samuel