2

How can I get this to compile? The error is when I start using boost::ref(). I thought boost::ref is used to pass reference to C++ algorithm classes?

  list<Object> lst;
  lst.push_back(Object(1,2.0f));
  lst.push_back(Object(3,4.3f));

  struct between_1_and_10
  {
    int d;
    void operator() (Object& value) 
    { 
      value.a += 5; value.b -= 3.3f; 
      cout << d << endl;
      d += value.a;
    }
  };

  between_1_and_10 val;
  val.d = 4;
  for_each(lst.begin(), lst.end(), boost::ref(val));   // Problem is here
  printf("rg");

EDIT Here's the compiler error as people suggested:

1>c:\program files (x86)\microsoft visual studio 9.0\vc\include\algorithm(29) : error C2064: term does not evaluate to a function taking 1 arguments
1>        c:\users\swangrun\desktop\minescout work\feat-000-gettargetimages\minescouttest\maintest.cpp(102) : see reference to function template instantiation '_Fn1 std::for_each<std::list<_Ty>::_Iterator<_Secure_validation>,boost::reference_wrapper<T>>(_InIt,_InIt,_Fn1)' being compiled
1>        with
1>        [
1>            _Fn1=boost::reference_wrapper<main::between_1_and_10>,
1>            _Ty=Object,
1>            _Secure_validation=true,
1>            T=main::between_1_and_10,
1>            _InIt=std::list<Object>::_Iterator<true>
1>        ]
4
  • Ok. Its supposed to be on the for_each() line. But what is the problem. You either have to give us the error or enough code that we can reproduce the error. Commented Jul 8, 2009 at 1:43
  • the problem is that it does not compile. i have accepted an answer, thank you for your participation! Commented Jul 8, 2009 at 1:50
  • What Martin meant is "Copy the text of the error message and paste it into your question". That way, we can explain to you what the compiler is saying. It probably gave you all the information you needed to find the error. At the least, you should do this so other people who search for the text of the compiler error can find the question and its answer. Commented Jul 8, 2009 at 1:58
  • thank you! sorry for misunderstanding your intent. Commented Jul 8, 2009 at 2:20

3 Answers 3

12

boost::reference_wrapper (which is what boost::ref returns) does not overload operator(). You can use it with boost::bind, which has special treating for it (not using ref would make bind copy the provided function object).

But for_each returns the function object it invokes the stuff on. So just do this

between_1_and_10 val;
val.d = 4;
val = for_each(lst.begin(), lst.end(), val);
printf("rg");

It will call the stuff on the copied val, and return the function object as it's after the last invocation.


Just to tell you where you might use boost::ref, because you seem to misuse it. Imagine a template that takes its parameter by value, and calls another function:

void g(int &i) { i++; }

template<typename T>
void run_g(T t) { g(t); }

If you now want to call it with a variable, it will copy it. Often, that's a reasonable decision, for example if you want to pass data to a thread as start parameters, you could copy it out of your local function into the thread object. But sometimes, you could want not to copy it, but to actually pass a reference. This is where boost::reference_wrapper helps. The following actually does what we expect, and outputs 1:

int main() { 
  int n = 0; 
  run_g(boost::ref(n)); 
  std::cout << n << std::endl;
}

For binding arguments, a copy is a good default. It also easily makes arrays and functions decay to pointers (accepting by reference would make T be possibly an array/function-type, and would cause some nasty problems).

Sign up to request clarification or add additional context in comments.

Comments

7

This what you really want:

for_each(lst.begin(), lst.end(), boost::bind<void>(boost::ref(val),_1  ) );

EDIT: Some explanation upon the OP's request. Recall that for_each() takes a function, but you were merely passing it a reference to your struct (yes, the struct has it's operator() overloaded but you were not passing that). bind() basically "exposes" the function inside your struct.

EDIT2: Explanation of the "_1" can be found in the comments below.

4 Comments

thank you. Exactly what I was looking for. If it's not too troublesome, could you please elaborate why bind is necessary..and what's that funny-looking _1? I'm sorry, I'm new to Boost. (unless of course, there's a good tutorial somewhere of the techniques you just used.)
Bind is probably necessary because the compiler couldn't deduce the return type of the function wrapped in boost:ref. As for the "_1", you can read about it here: boost.org/doc/libs/1_39_0/libs/bind/bind.html#with_functions
-1, the _1 is the lambda placeholder. It actually represents the "current" item being pointed to by for_each's iterator.
Yeah, no offense, but that EDIT-explanation actually is quite weird.
-1

Try it without the boost::ref.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.