On Thu, Oct 23, 2008 at 7:21 AM, Raindog <raindog@macrohmasheen.com> wrote:
I ran into a problem while cleaning up some old code. What I wanted to do was replace explicit for loops with some stl algorithms or BOOST_FOREACH. Below is the original function:

|//in header file:
..snip
typedef std::vector<Loki::SmartPtr<ADTChunk> > chunk_vec_t
chunk_vec_t chunks;
..snip

//in source file:
uint32_t ADT::get_connectivity_data( std::vector< std::vector<uint8_t> > &output )
{
      output.resize(chunks.size());
      for(chunk_vec_t::iterator it = chunks.begin(); it < chunks.end(); ++it)
      {
              uint32_t success = (*it)->get_connectivity_data(output[it-chunks.begin()]);
      }
      return TRUE;
}

I asked on a separate website for some possibilities of replacing this code with boost::lambda, and the following almost correct suggestion was given to replace the loop:

||std::for_each( chunks.begin(), chunks.end(),              bind( &chunk_vec_t::value::type::get_connectivity_data,                    _1,                    output[ std::distance( _1, chunks.begn()  ]                  )
           );

The problem is that the above obviously does not compile, so I made some changes and came up with this:

||std::for_each( chunks.begin(), chunks.end(),              bind( &chunk_vec_t::value_type::StoredType::get_connectivity_data,                    _1,                    output[ std::distance( &_1, &chunks[0] ) ]                  )
           );

The problem with the above is that "||&chunk_vec_t::value_type::StoredType::get_connectivity_data|" causes the VC9 compiler to crash =(

So I made this change:

|std::for_each( chunks.begin(), chunks.end(),              bind( &ADTChunk::get_connectivity_data,                    _1,                    output[ std::distance( _1, chunks.begin() ) ]                  )
           );

But now I get an error with the call to std::distance not being able to discern the arguments due to ambiguity.

Next I thought that I might be able to use zip_iterator to assist in dealing with both of the containers, and then I realized it used tuples,
which then made me thing that extracting the iterators from the tuples is going to take a lot of boiler plate code itself. Which led me to settle with
the following code that is concise and easily readable but will only work if chunks is a vector essentially:

       BOOST_FOREACH(chunk_vec_t::value_type it, chunks)
       {
               output[std::distance(&it, &chunks[0])] = it->get_connectivity_data();
       }

So, my final question is, given my above attempts, is there a way to do what the 1st and 5th(the one immediately above this line) code snippets do
in a straight-forward manner using either boost::lambda, or, since it will be replaced eventually by phoenix v3, with phoenix v2?


I confess to having only given this a cursory glance over the first coffee of the day, but
isn't this essentially a transform operation, for which the transform algorithm would be
the clearest solution?

Cheers, Rob.