Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Boost::ref correctly..?

Tags:

c++

boost

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>        ]
like image 305
sivabudh Avatar asked Jun 19 '26 17:06

sivabudh


1 Answers

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).

like image 67
Johannes Schaub - litb Avatar answered Jun 21 '26 05:06

Johannes Schaub - litb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!