Reputation: 32645
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> ]
Upvotes: 2
Views: 7166
Reputation: 755
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.
Upvotes: 7
Reputation: 507105
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).
Upvotes: 12