4

I try to transform all elements of a vector v into their log values with some other arithmetic operations (not in the code). How can I use Boost.Lambda to achieve that?

As I say, there are some more arithmetic operations, so an expression with Boost.Bind doesn't work for me (too complicated, too long, unreadable).

I don't want to use C++11 lambdas as well. But... would it change anything?

My code is like:

#include <boost/lambda/lambda.hpp>
#include <cmath>
#include <vector>

void testLambda()
{
    using namespace boost::lambda;

    std::vector<double> v;
    v.push_back(1); v.push_back(2); v.push_back(3);

    std::transform(v.begin(), v.end(), v.begin(), _1 / 0.5);     // works
    std::transform(v.begin(), v.end(), v.begin(), log(_1) / 0.5);   // produces error
    //std::transform(v.begin(), v.end(), v.begin(), std::log(_1) / 0.5);   // produces error
    //std::transform(v.begin(), v.end(), v.begin(), static_cast<double(*)(double)>(std::log)(_1) / 0.5);   // produces error
}

When I try to compile the code, MSVC2010 gives the error:

Error   1   error C2665: 'log' : none of the 3 overloads could convert all the argument types
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\math.h(120): could be 'double log(double)'
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\math.h(527): or       'float log(float)'
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\math.h(575): or       'long double log(long double)'
while trying to match the argument list '(boost::lambda::placeholder1_type)'

Update 1: I don't want to write functors for it, think that I would have to have a dozen of them, what then?

Update 2: I am able to do it with C++11 lambdas, but it's not what I ask for:

   std::transform(v.begin(), v.end(), v.begin(), [](const double & x) { return log(x) / 0.5; });
Marek Kurdej
  • 1,459
  • 1
  • 17
  • 36
  • http://stackoverflow.com/a/1931602/98654 has an example of using multiple lambda/binds together -- is that what you are looking for? – Nate Kohl Jul 18 '13 at 14:30
  • 1
    just write a plain old function object – TemplateRex Jul 18 '13 at 14:33
  • @NateKohl I cannot get it work together lambdas and bind. Can you give a solution, please? – Marek Kurdej Jul 18 '13 at 14:46
  • It might help if you provide an example of the actual transformations that you'd like to perform. (Just needing to do `log` is a good case for `std::bind` or `boost::bind`.) – Nate Kohl Jul 18 '13 at 14:53
  • Things that could solve your problem that you ruled out: explicit loops, writing a function that does what you want, `bind`, `[](){}` lambdas, writing a functor, `std::function`, `auto`... Did I miss anything? – Yakk - Adam Nevraumont Jul 18 '13 at 15:16

1 Answers1

2

How about a proper C++11 lamba? MSVC2010 has limited support, but plain math should work fine.

std::transform(v.begin(), v.end(), v.begin(), [](const double& x) { return log(x); });

Or an old-school solution to the problem:

struct f
{
   double operator()(const double& x)
   {
     return log(x);
   }
}
std::transform(v.begin(), v.end(), v.begin(), f);

Anyways, I see no need for fancy lambda stuff in the code you posted since you seem to be modifying the vector's elements in-place:

std::vector<double> v;
v.push_back(1); v.push_back(2); v.push_back(3);
for(const std::vector<double>::iterator it = v.begin(); it != v.end(); ++it)
{
  /* fancy math stuff here */
  *it = log(*it);
}

This is IMHO the cleanest way to do this. My final C++ solution (by far the most expressive and simplest of every alternative) would be:

for(auto&& x : v)
{
  /* fancy math stuff here */
  x = log(x);
}
rubenvb
  • 74,642
  • 33
  • 187
  • 332
  • I don't want C++11 lambdas, nor functors. The former -- C++03 constrained. The latter -- unreadable if there are lots of them. – Marek Kurdej Jul 18 '13 at 14:40
  • @Curdeius I'd guess you're out of luck; Boost.Lambda's documentation has an example `int foo(int); for_each(v.begin(), v.end(), _1 = bind(foo, _1));` which does wat you want, but uses `bind`. C++03 is just not a functional language. What prevents you from just using a `for` loop? – rubenvb Jul 18 '13 at 14:59
  • Nothing prevents me from doing a ```for``` loop, I just wanted to be consistent with the rest of my code. – Marek Kurdej Jul 18 '13 at 18:45