I have a test map with pair of std::string and Person pointer
class MyMap {
public:
void clear() {
std::for_each(people.begin(), people.end(),std::bind1st(std::mem_fun(&MyMap::remove), this));
}
void remove(std::pair<std::string, Person*> p) { delete p.second; }
private:
std::map<name, Person*> people;
};
My question is does for_each pass each Person pair by ref or value? is it worth using my own, this is a bit cleaner.
In addition to that if I want to use boost::bind or std::bind (c++11) instead of bind1st, how would I do it? should this function be like struct having operator() that inherits std::unary_function?
The type of the map is std::map<name, Person*>, but the parameter for the remove function is std::pair<std::string, Person*>. This won't work unless name is typedef for std::string.
The way your remove function is currently defined, you'll make copies of the map's value_type. Change the function signature to:
void remove(std::pair<const std::string, Person *>& p)
// ^^^^^ ^
// key must be const take a reference
To use std::bind instead of std::bind1st
std::for_each( people.begin(),
people.end(),
std::bind( &MyMap::remove, this, std::placeholders::_1 ) );
But if you can use C++11 features, there's no need for std::bind, lambda is much nicer.
std::for_each( people.begin(),
people.end(),
[]( decltype(*people.begin())& p ) { delete p.second; } );
or use a range based for loop
for( auto&& p : people ) {
delete p.second;
}
for_each will call the functor either by-value or by-reference, depending on how you have defined the functor.
For example:
struct Gizmo
{
bool operator() (const Zippy& rhs) const
{
// ...
}
};
This functor is call-by-ref. However:
struct Gizmo
{
bool operator() (Zippy rhs) const
{
// ...
}
};
This one is call-by-value.
Related
I'm trying to figure out a nice way to find the index of a certain object in a vector - by comparing a string to a member field in the object.
Like this:
find(vector.begin(), vector.end(), [object where obj.getName() == myString])
I have searched without success - maybe I don't fully understand what to look for.
You can use std::find_if with a suitable functor. In this example, a C++11 lambda is used:
std::vector<Type> v = ....;
std::string myString = ....;
auto it = find_if(v.begin(), v.end(), [&myString](const Type& obj) {return obj.getName() == myString;})
if (it != v.end())
{
// found element. it is an iterator to the first matching element.
// if you really need the index, you can also get it:
auto index = std::distance(v.begin(), it);
}
If you have no C++11 lambda support, a functor would work:
struct MatchString
{
MatchString(const std::string& s) : s_(s) {}
bool operator()(const Type& obj) const
{
return obj.getName() == s_;
}
private:
const std::string& s_;
};
Here, MatchString is a type whose instances are callable with a single Type object, and return a boolean. For example,
Type t("Foo"); // assume this means t.getName() is "Foo"
MatchString m("Foo");
bool b = m(t); // b is true
then you can pass an instance to std::find
std::vector<Type>::iterator it = find_if(v.begin(), v.end(), MatchString(myString));
In addition to the Lambda and the handwritten functor used by juancho, you have the possibility to use boost::bind (C++03) or std::bind (C++11) and a simple function:
bool isNameOfObj(const std::string& s, const Type& obj)
{ return obj.getName() == s; }
//...
std::vector<Type>::iterator it = find_if(v.begin(), v.end(),
boost::bind(&isNameOfObj, myString, boost::placeholders::_1));
Or, if Type has a method isName:
std::vector<Type>::iterator it = find_if(v.begin(), v.end(),
boost::bind(&Type::isName, boost::placeholders::_1, myString));
This is just for completeness. In C++11 I'd prefer Lambdas, in C++03 I'd use bind only if the comparison function itself exists already. If not, prefer the functor.
PS: Since C++11 has no polymorphic/templated lambdas, bind still has it's place in C++11, e.g. if the parameter types are unknown, hard to spell, or otherwise not easy to deduce.
A simple iterator may help.
typedef std::vector<MyDataType> MyDataTypeList;
// MyDataType findIt should have been defined and assigned
MyDataTypeList m_MyObjects;
//By this time, the push_back() calls should have happened
MyDataTypeList::iterator itr = m_MyObjects.begin();
while (itr != m_MyObjects.end())
{
if(m_MyObjects[*itr] == findIt) // any other comparator you may want to use
// do what ever you like
}
Suppose I have a vector of shared pointers of objects of class A. I want to collect all the return values of method A::foo for all of the A objects and store them in some container, say another vector.
Can this be done with std::transform or std::for_each and std::bind or some boost function ?
class A {
public:
string foo(int p);
};
std::vector<shared_ptr<A>> vec;
std::transform is fine for this:
std::vector<std::string> string_vec;
const int magic_number = 42;
std::transform(std::begin(vec),
std::end(vec),
std::back_inserter(string_vec),
[magic_number](std::shared_ptr<A> a){ return a->foo(magic_number); } );
Obviously, you need to figure out which int you want to pass to A::foo(int).
In C++03, you can replace the lambda by a functor or function:
struct get_foo
{
get_foo(int n) : n_(n) {}
bool operator() (std::shared_ptr<A> a) const { return a->foo(n); }
private:
int n_;
};
const int magic_number = 42;
std::vector<std::string> string_vec;
std::transform(std::begin(vec),
std::end(vec),
std::back_inserter(string_vec),
get_foo(magic_number));
I have a vector of objects. My data structure is the following:
class my_class{
float a; int b;
};
my_class obj;
vector<my_class> vec;
The vector vec contains data of the form:
vec
((10.0,2),(100,3),(19.0,3)...)
Now from vector vec I intend to delete the elements which are less than or equal to the last element of vec...For this I am using erase and remove_if functions:
vec.erase(std::remove_if(vec.begin(), vec.end(), predicate_function(vec, (vec.end()-1).a, (vec.end()-1).b)), vec.end());
The predicate_function which I have does an iteration over "vec". However, this defeats the purpose of using std::remove_if. Can someone please help as to what the predicate_function should look like in order for remove_if to work. I dont want to use lambda_function. Also my compiler is GCC
The predicate function will automatically be passed the parameters from each Iterator. So it'd look something like:
bool predicate_function(const my_class& m)
{
//Some logic here
}
Which would then simply be called as:
vec.erase(std::remove_if(vec.begin(), vec.end(), predicate_function), vec.end());
In C++ terms, std::remove_if expects a UnaryPredicate as its 3rd parameter, which is either a function or functor accepting 1 argument and returning bool.
Edit: To do what you want in the comment, you'd need to use a functor (or std::bind, but we'll go the functor route here):
struct compare_last
{
const my_class last_;
compare_last(const my_class& last)
: last_(last)
{ }
bool operator()(const my_class& m) const
{
return m == last_; //Or however you do your comparisons
}
};
my_class& last = *(--vec.end());
vec.erase(std::remove_if(vec.begin(), vec.end(), compare_last(last)), vec.end());
I have:
struct MyStruct
{
char* name;
int* somethingElse;
};
And I need to find in a std::vector<MyStruct*> an element (by using std::find_if) whose name is "XYZ" ... but ... the Predicate of std::find_if (if I have managed to understand it correctly) is a plain function, and it takes in a MyStruct pointer and I have no idea where I can specify the extra "XYZ" value to be used in the comparison.
So, how can I use std::find_if or this purpose? (Obviously, looking for a nice solution, not a global variable, or just walk through the list, ....)
Thanks, f
You can use a functor for this (hope I didn't get anything wrong, as I typed it in the browser):
class finder
{
const char* name;
public:
finder(const char* _name): name(_name) {}
bool operator()(MyStruct* elem) {return strcmp(elem->name, name) == 0;}
};
finder f("sample");
std::find_if(myvector.begin(), myvector.end(), f);
If you use C++11 and lambda:
std::vector<MyStruct> mystructus;
std::find_if(mystructus.begin(), mystructus.end(),
[](const MyStruct& ms){ return ms.name == std::string("XYZ"); } );
You have two options, either use functors or lamdas.
Using functors, you create a new class (or structure) whose constructor takes the string you want to search for, then it has an operator() function that is called by std::find_if:
class my_finder
{
std::string search;
public:
my_finder(const std::string& str)
: search(str)
{}
bool operator()(const MyStruct* my_struct) const
{ return search == my_struct->name; }
};
// ...
std::find_if(std::begin(...), std::end(...), my_finder("XYZ"));
The second using lambdas is less code, but requires recent version of the compiler that can handle C++11 lambdas:
std::find_if(std::begin(...), std::end(...), [](const MyStruct* my_struct)
{ return std::string("XYZ") == my_struct->name; });
The last example can even be generalized further:
using namespace std::placeholders; // For `_1` used below in `std::bind`
// Declare a "finder" function, to find your structure
auto finder = [](const MyStruct* my_struct, const std::string& to_find) {
return to_find == my_struct->name;
};
auto xyz = std::find_if(std::begin(...), std::end(...), std::bind(finder, _1, "XYZ"));
auto abc = std::find_if(std::begin(...), std::end(...), std::bind(finder, _1, "ABC"));
This way the lambda can be reused.
Predicate is anything, that can have operator () applied to it (with the expected argument(s) and returns something convertible to bool). A pointer to function is such thing, but so is an object that defines operator().
You need to provide a predicate like this:
struct Comparator
{
Comparator(const char* find) : m_find(find){}
bool operator()(MyStruct* p) const
{
return strcmp(p->name, m_find) == 0;
}
const char* m_find;
};
Then you can std::find_if like this:
vector<MyStruct*>::iterator iter = std::find_if(vec.begin(), vec.end(), Comparator("XYZ"));
if(iter != vec.end())
{
MyStruct* p = *iter;
}
Or if your compiler supports C++11 you can use lambdas and get rid of the predicate functor:
auto it = std::find_if(vec.begin(), vec.end(), [](MyStruct* p) { return strcmp(p->name, "XYZ") == 0;});
I'd like to use the boost::transform_iterator together with boost::bind to return the result of a member function.
e.g.
class Foo
{
public:
//...
Bar& getBar();
const Bar& getBar() const;
};
I've got a unary Function object to select the getBar() function
struct getBar: public std::unary_function<Foo&,Bar&>
{
getBar::result_type operator()(getBar::argument_type arg ) const {
return arg.getBar()
}
};
and lets say i've stored several Foo objects inside a std::vector and Im using a tranform_iterator like that
int main()
{
typedef std::vector<Foo> VEC;
typedef boost::transform_iterator<getBar,VEC::iterator> iterator;
VEC vec;
vec.push_back( Foo ());
iterator i( vec.begin() );
//...
Bar = *i;
return 0;
};
But if i want to use boost::bind instead of the getBar functor how would i do that. I'm not sure which template parameter I would have to pass to the transform_iterator.
EDIT:
the solution with boost::function was a good start but i wasn't completely satisfied so experimented a bit and looked into the return type of boost::mem_fn
typedef boost::transform_iterator<boost::_mfi::mf0<Bar&,Foo>,VEC::iterator> iter;
typedef boost::transform_iterator<boost::_mfi::cmf0<const Bar&,Foo>,VEC::const_iterator> citer;
but this solution has another problem.
because
iter i(v.begin(), boost::mem_fn( &Foo::getBar ));
citer ci(v.begin(), boost::mem_fn( &Foo::getBar ));
leads to the following error
call of overloaded mem_fn(<unresolved overloaded function type>) is ambiguous
the compiler is not able to identify which getBar function is requested and I had to help him a little.
iter i(v.begin(), boost::mem_fn( static_cast<Bar& (Foo::*)()>(&Foo::getBar) ));
citer ci(v.begin(), boost::mem_fn( static_cast<const Bar& (Foo::*)() const >(&Foo::getBar) ));
this is probably not faster than writing a little functor by hand but at least it helped me to understand boost::mem_fn a bit more.
boost::transform_iterator<boost::function<Bar&(Foo&)>,std::vector<Foo>::iterator>