In the past I've used the bind1st and bind2nd functions in order to do straight forward operations on STL containers. I now have a container of MyBase class pointers that are for simplicities sake the following:
class X
{
public:
std::string getName() const;
};
I want to call the following static function using for_each and binding both the 1st and 2nd parameters as such:
StaticFuncClass::doSomething(ptr->getName(), funcReturningString() );
How would I use for_each and bind both parameters of this function?
I'm looking for something along the lines of:
for_each(ctr.begin(), ctr.end(),
bind2Args(StaticFuncClass::doSomething(),
mem_fun(&X::getName),
funcReturningString());
I see Boost offers a bind function of its own that looks like something that would be of use here, but what is the STL solution?
Thanks in advance for your responses.
A reliable fallback when the bind-syntax gets too weird is to define your own functor:
struct callDoSomething {
void operator()(const X* x){
StaticFuncClass::doSomething(x->getName(), funcReturningString());
}
};
for_each(ctr.begin(), ctr.end(), callDoSomething());
This is more or less what the bind functions do behind the scenes anyway.
The "STL solution" would be to write your own binder... that's why they created the powerful boost::bind.
You can either create a local functor structure, which can be inlined by the compiler (as Jalf showed), or use a simple function:
void myFunc( const X* x ) {
StaticFuncClass::doSomething(x->getName(), funcrReturningString() );
}
for_each( c.begin(), c.end(), myFunc );
Related
bool all_ok = boost::algorithm::all_of(info.begin(), threadInfo.end(), [&](std::pair<std::string, Info> const &p){ return p.second.am_ok; });
Above is a line I am trying to remove c++11 from (in order to be compliant with an application I am integrating with, if you must know). I would like to replace the lambda without defining a function external to the current method.
My question is, how can I utilize boost::bind to represent a function & binding that takes in a single input and returns a boolean?
If you really want to use boost::bind to do this, it would look something like this:
boost::bind(&Info::am_ok, boost::bind(&std::pair<std::string, Info>::second, _1));
Boost.Bind supports composition of its function objects, so in this case the function object created by the nested bind gets called first, and its result (the Info object) is passed to the enclosing function object, which returns the am_ok member of the structure.
You see that the code is somewhat contrived, so you'll probably want to write a custom function object anyway.
struct is_ok
{
typedef bool result_type;
result_type operator() (std::pair<std::string, Info> const &p) const
{
return p.second.am_ok;
}
};
I have made a small example in order to understand how boost::bind () works with collections. I have a class called Data:
class Data
{
public:
void print ();
const std::string& get () const;
std::string& get () ;
};
I have created a std::vector of Data objects called samples and I am able to use bind in the same way as std::mem_fun_ref works.
std::for_each (samples.begin (),samples.end (),std::mem_fun_ref (&Data::print));
std::for_each (samples.begin (),samples.end (),boost::bind (&Data::print,_1));
The basic idea is that the bind returns a function object of type bind_t<RetType=void, ObjType=Data, ArgType=void>. The member function as the first parameter allows the compiler to deduce RetType, ObjType and ArgType. The placeholder _1 corresponds to the data object which must be provided by the algorithm.
Then std::for_each calls the function object "for each" element in the following way:
for ( ; first!=last; ++first ) f(*first);
bind_t::operator(ObjType& obj) is invoked and its definition should be something like this:
return (obj.*_method ());
I have crated a class called Filter that performs some processing over a data element.
class Filter
{
void filter (Data& data);
...
};
If I want to apply the filter over the data elements in the vector I call bind in the following way:
std::for_each (samples.begin (),samples.end (),boost::bind (&Filter::filter,filter,_1));
for_each passes a Data object to bind_t::operator(). In this case the function object already has the object and just need the parameter so in this case placeholder _1 refers to the argument.
Here comes my question:
How can use bind if I have to iterate over a std::map rather than a vector?
(Sorry for all the explanation, I just want to make sure that I understand the way in which bind works)
#include <boost/bind.hpp>
#include <algorithm>
int main()
{
struct Sample
{
int i_;
double d_;
};
typedef std::map<int, Sample> Samples;
struct Filter
{
void filter(const Sample &s)
{
}
};
Filter filter;
Samples samples;
std::for_each(samples.begin(), samples.end(), boost::bind(&Filter::filter, filter, boost::bind(&Samples::value_type::second, _1)));
}
Of course, you can use bind() to iterate over a std::map<...>. However, note that the elements in the std::map<K, V> have the type std::pair<K const, V> i.e. the bound function needs to be cable of accessing objects of this type. That said, I'm not aware that bind() alone can be used to transform this argument into the argument you are actually interested (i.e. to a V). To do this, you probably need an auxiliary function which is called to do the transformation. If you bind() this function as well bind() can do a suitable composition, i.e. I think something like this should work:
template <typename Result>
struct project2nd {
typedef Result const& result_type;
template <typename T>
result_type operator()(std::pair<T, Result> const& arg) const {
return arg.second;
}
};
...
... bind(&Filter::filter, filter, bind(project2nd<Data>(), _1)) ...
For bind() to work with a funciton object it seems it needs some information about related types: the result of the function call operator can't be deduced but is apparently needed internally. I assume that bind() is clever enough to pass references through. Otherwise the type needs to be changed to be Result. Also, I don't know if bind() also needs to know about the argumen type. If so, the project2nd class tmeplate would need to take both types as argument.
This cites for_each as follows:
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);
I have a collection std::list<std::string>, and a function void Do(std::string) works fine when given to for_each along with the iterators. But if I supply a function like void Do(std::string&), it does not compile. Is there a way around it? Or should I forget about it as some RVO like magic is going on? :D
EDIT:
bool PluginLoader::LoadSharedObjects()
{
for_each(l_FileNames.begin(), l_FileNames.end(), bind1st(mem_fun(&PluginLoader::LoadSharedObject),this));
}
void PluginLoader::LoadSharedObject(const std::string sFileName)
{
void* pHandle = dlopen(sFileName.c_str(), i_LibMode);
//if(pHandle == NULL)
//Check dlerror
//Add handle to list
}
Code added. I woul like LoadSharedObject function to be of the form void PluginLoader::LoadSharedObject(const std::string& sFileName) if it is possible.
The error is not with for_each but with bind1st and mem_fun. They simply dont't support what you're trying to do. They cannot handle functions which take reference parameters. You could write your own functor, use boost::bind or wait until you're able to use C++0x lambdas.
Example for your own functor:
struct LoadSharedObjFunctor
{
PluginLoader *pl;
public:
explicit(PluginLoader *p)
: pl(p) {}
void operator()(std::string const& cref) const
{ return pl->LoadSharedObject(cref); }
};
...
std::for_each(...,...,LoadSharedObjFunctor(this));
...
Of course, you don't have to use std::for_each. A simple for-loop will do as well.
If you are allowed to use boost, then what you want is boost:::bind.
#include <boost/bind.hpp>
...
for_each(l_FileNames.begin(),
l_FileNames.end(),
boost::bind(&PluginLoader::LoadSharedObject, this, _1));
Just for fun, here is why what you are trying doesn't work:
This mem_fun(&PluginLoader::LoadSharedObject) creates an object of type mem_fun1_t<void, PluginLoader, const string &>.
So bind1st(mem_fun(&PluginLoader::LoadSharedObject),this) creates an object of type binder1st< mem_fun1_t<void, PluginLoader, const string &> >.
The problem is that binder1st defines a function that looks like:
ResultType operator()(const ArgType &), where ArgType is const string &. So effectively it means you are trying to form a reference to a reference.
The current standard isn't clear whether such usage of for_each should be allowed or not, and different implementations behave differently - some accept that but some not. That was considered unfortunate by some people, so C++0x is going to fix the situation by explicitly allowing mutating operations passed to for_each if the iterator is modifiable.
On the EDIT: const references aren't a problem. What errors do you get?
I have a one-dimensional function minimizer. Right now I'm passing it function pointers. However many functions have multiple parameters, some of which are held fixed. I have implemented this using functors like so
template <class T>
minimize(T &f) {
}
Functor f(param1, param2);
minimize<Functor>(f);
However the functor definition has lots of crud. Boost::bind looks cleaner. So that I could do:
minimize(boost:bind(f,_1,param1,param2))
However I'm not clear what my minimize declaration should like like using boost::bind. What type of object is boost::bind? Is there an easy pattern for this that avoids the boilerplate of functors but allows multiple parameter binding?
You can just use boost::function. I think boost::bind does have its own return type, but that is compatible with boost::function. Typical use is to make a typedef for the function:
typedef boost::function<bool(std::string)> MyTestFunction;
and then you can pass any compatible function with boost::bind:
bool SomeFunction(int i, std::string s) { return true; }
MyTestFunction f = boost::bind(SomeFunction, 42, _1);
f("and then call it.");
I hope that is what you want.
It also works with methods by passing the this pointer for the call as second parameter to boost::bind.
I would define minimize() this way:
minimize(boost::function< return_type(param_type1,param_type2,param_type3,...)> f)
{
...
}
Then you could call minimize() like this:
minimize(boost::bind(&class::function,actual_object,_1,_2,_3,...));
Change the parameter to a value parameter. Function objects are intentionally light weight, and boost::bind certainly is, specially crafted to fit in within space of a few bytes using boost::compressed_pair and what not.
template <class T>
void minimize(T f) {
}
Then you can pass it the result of boost::bind. Remember that boost::bind is actually a function template that returns some object of some type. So having minimize have a non-const reference parameter couldn't work.
First, you are taking your template argument as a ref-to-non-const, so the temporary returend by boost::bind won't bind to it. So you can use it like:
template <class T>
T::result_type minimize(const T &f) {
}
But if you wanted to use this with your Functors as well, they would have to have a const operator(). So perhaps by value is better:
template <class T>
T::result_type minimize(T f) {
}
I believe having the return be T::result_type will force a T to be a boost::function (rather than the complicated type bind returns), but I'm not 100%
I'm trying to use stl algorithm for_each without proliferating templates throughout my code. std::for_each wants to instantiate MyFunctor class by value, but it can't since its abstract. I've created a functor adapter class which passes a pointer around and then derefernces it when appropriate.
My Question:
Does the STL or Boost already have such an adapter class? I don't want to have to reinvent the wheel!
struct MyFunctor {
virtual ~MyFunctor() {}
virtual void operator()(int a) = 0;
}
namespace {
template<typename FunctorType, typename OperandType> struct
FunctorAdapter
{
FunctorAdapter(FunctorType* functor) : mFunctor(functor) {}
void operator()(OperandType& subject)
{
(*mFunctor)(subject);
}
FunctorType* mFunctor;
}; }
void applyToAll(MyFunctor &f) {
FunctorHelper<MyFunctor, int> tmp(&f);
std::for_each(myvector.begin(), myvector.end(), tmp); }
Cheers,
Dave
You could use the function adapters (and their shims) from functional.
#include <functional>
using namespace std;
for_each( vec.begin(), vec.end(), :mem_fun_ptr( &MyClass::f ) );
If your container contains pointers-to-objects, use mem_fun_ptr, else use mem_fun. Next to these, there are wrappers for member functions that take 1 argument: mem_fun1_ptr and mem_fun1.
#Evan: indeed, you could call the member function with the same argument for each object. The first argument of the mem_fun1 wrappers is the this pointer, the second is the member function argument:
for_each( vec.begin(), vec.end(), bind2nd( mem_fun_ptr( &MyClass::f ), 1 ) );
With more arguments, it becomes more readable to create a loop yourself, or create a custom functor that has const member variables representing the arguments.
tr1::ref may help you here --- it's meant to be a reference wrapper so that you can pass normal objects by reference to bind or function objects (even abstract ones) by reference to standard algorithms.
// requires TR1 support from your compiler / standard library implementation
#include <functional>
void applyToAll(MyFunctor &f) {
std::for_each(
myvector.begin(),
myvector.end(),
std::tr1::ref(f)
);
}
However, NOTE that compilers without decltype support MAY reject passing a reference to an abstract type... so this code may not compile until you get C++0x support.
why not use BOOST_FOREACH?
http://www.boost.org/doc/libs/1_35_0/doc/html/foreach.html
Sounds like you could benefit from Boost::Function.
If I remember correctly it's a header only library too, so it's easy to get it going with it.
What about forgetting all the wrapping of the functor pointer, and instead use
bind(functor_pointer,mem_fun1(&MyFunctor::operator());
as the functor? that way, you don't have to worry about managing the copy in any way shape or form.
Building on #xtofl's answer, since the array contains int's and not "this" pointers, I think the correct incantation is
class MyClass
{
virtual void process(int number) = 0;
};
MyClass *instance = ...;
for_each( vec.begin(), vec.end(), binder1st(instance, mem_fun_ptr(&MyClass::process) );
The only difference versus #xtofl's code is binder1st rather than binder2nd. binder2nd allows you to pass teh same number to various "this" pointers. binder1st allows you to pass various numbers to one "this" pointer.