Polymorphic functors in std::for_each - c++

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.

Related

How to pass a container of derived type to a function needing a container of base type [duplicate]

Consider these classes.
class Base
{
...
};
class Derived : public Base
{
...
};
this function
void BaseFoo( std::vector<Base*>vec )
{
...
}
And finally my vector
std::vector<Derived*>derived;
I want to pass derived to function BaseFoo, but the compiler doesn't let me. How do I solve this, without copying the whole vector to a std::vector<Base*>?
vector<Base*> and vector<Derived*> are unrelated types, so you can't do this. This is explained in the C++ FAQ here.
You need to change your variable from a vector<Derived*> to a vector<Base*> and insert Derived objects into it.
Also, to avoid copying the vector unnecessarily, you should pass it by const-reference, not by value:
void BaseFoo( const std::vector<Base*>& vec )
{
...
}
Finally, to avoid memory leaks, and make your code exception-safe, consider using a container designed to handle heap-allocated objects, e.g:
#include <boost/ptr_container/ptr_vector.hpp>
boost::ptr_vector<Base> vec;
Alternatively, change the vector to hold a smart pointer instead of using raw pointers:
#include <memory>
std::vector< std::shared_ptr<Base*> > vec;
or
#include <boost/shared_ptr.hpp>
std::vector< boost::shared_ptr<Base*> > vec;
In each case, you would need to modify your BaseFoo function accordingly.
Instead of passing the container object (vector<>), pass in begin and end iterators like the rest of the STL algorithms. The function that receives them will be templated, and it won't matter if you pass in Derived* or Base*.
This problem occurs in programming languages that have mutable containers. You cannot pass around a mutable bag of apples as a bag of fruit because you cannot be sure that someone else does not put a lemon into that bag of fruit, after which it no longer qualifies as a bag of apples. If the bag of apples were not mutable, passing it around as a bag of fruit would be fine. Search for covariance/contravariance.
one option is to use a template
template<typename T>
void BaseFoo( const std::vector<T*>& vec)
{
...
}
The drawback is that the implementation has to be in the header and you will get a little code bloat. You will wind up with different functions being instantiated for each type, but the code stays the same. Depending on the use case it's a quick and dirty solution.
Edit, I should note the reason we need a template here is because we are trying to write the same code for unrelated types as noted by several other posters. Templates allow you do solve these exact problems. I also updated it to use a const reference. You should also pass "heavy" objects like a vector by const reference when you don't need a copy, which is basically always.
Generally you would start with a container of base pointers, not the other way.
If you dealing with a third-party library, and this is your only hope, then you can do this:
BaseFoo (*reinterpret_cast<std::vector<Base *> *>(&derived));
Otherwise fix your code with one of the other suggesstions.
Taking Matt Price's answer from above, given that you know in advance what types you want to use with your function, you can declare the function template in the header file, and then add explicit instantiations for those types:
// BaseFoo.h
template<typename T>
void BaseFoo( const std::vector<T*>& vec);
// BaseFoo.cpp
template<typename T>
void BaseFoo( const std::vector<T*>& vec);
{
...
}
// Explicit instantiation means no need for definition in the header file.
template void BaseFoo<Base> ( const std::vector<Base*>& vec );
template void BaseFoo<Derived> ( const std::vector<Derived*>& vec );
If std::vector supported what you're asking for, then it would be possible to defeat the C++ type system without using any casts (edit: ChrisN's link to the C++ FAQ Lite talks about the same issue):
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
void pushStuff(std::vector<Base*>& vec) {
vec.push_back(new Derived2);
vec.push_back(new Base);
}
...
std::vector<Derived1*> vec;
pushStuff(vec); // Not legal
// Now vec contains a Derived2 and a Base!
Since your BaseFoo() function takes the vector by value, it cannot modify the original vector that you passed in, so what I wrote would not be possible. But if it takes a non-const reference and you use reinterpret_cast<std::vector<Base*>&>() to pass your std::vector<Derived*>, you might not get the result that you want, and your program might crash.
Java arrays support covariant subtyping, and this requires Java to do a runtime type check every time you store a value in an array. This too is undesirable.
They are unrelated types -- you can't.

How to do function currying before c++11

I have a function which have two arguments, and I want bind the 2nd argument to a value and get a new function object.
What I want is perfectly supported by std::bind in c++ 11, for example:
int my_func(int a, int b) {...}
auto bind_func = std::bind (my_func,_1, 555);
Or in python:
bind_func = functools.partial(my_func, b=555)
But I want to do it in C++03, I know boost can do it but I don't want invoke boost for this simple requirement.
Now I wrote my own template to do it, but it will be perfect if I can use standard library.
Does anyone know how can I do it?
Thanks!
A functor is very easy to make. And that's the only way of currying functions in pre 2011 c++.
Example:
struct my_func_functor // choose a name
{
int curry_;
my_func_functor(int curry) : curry_(curry) {}
int operator()(int a) { return my_func(a, curry_); }
};
// to use...
vector<int> v;
//...
// build the functor with the curry and let transform do the cooking...
std::transform(v.begin(), v.end(), v.begin(), my_func_functor(555));
You can of course store anything you want in the functor. including references. This is the same model used behind the scene by C++11's lambdas. Instead of a capture clause, you have a constructor, and a structure to hold the data to pass along when the actual call is made through the operator().

What do we need unary_function and binary_function for?

I read the tutorials about the binary and unary functions. I understood the structure of them, but I couldn't imagine in which case I need these functions. Can you give an example for usage of them.
http://www.cplusplus.com/reference/std/functional/unary_function/
http://www.cplusplus.com/reference/std/functional/binary_function/
These aren't functions, these are classes (structs, actually, but doesn't matter). When you define your own binary functions to use with STL algorithms, you derive them from these classes in order to automatically get all the typedefs.
E.g.
struct SomeFancyUnaryFunction: public std::unary_function<Arg_t, Result_t>
{
Result_t operator ()(Arg_t const &)
{
...
}
};
now you don't need to manually provide the typedefs for argument_type, result_type etc. These structs, just like the iterator struct are there just for our convenience, in order to reuse the typedefs needed for algorithms.
Update for C++11:
As of C++11, the new std::bind does not really need any typedefs, so there are, in a way, obsolete.
Basically, they provide all the typedefs necessary to allow composition of higher-order functions from unary and binary function objects using function adaptors. For example, this allows using a binary functor where a unary is needed, binding one of the arguments to a literal value:
std::find_if( begin, end, std::bind1st(greater<int>(),42) );
std::bind1st relies on the functor passed to it to provide those types.
AFAIK the new std::bind doesn't need them, so it seems in new code you can use std::bindand do away with them.
There's an explanation on the sgi STL documentation of Function Objects. In summary, unary_function and binary_function are used to make functors adaptable. This allows them to be used with function object adaptors such as unary_negate.
What are they?
std::unary_function and std::binary_function are base structs for creation adaptable function objects. The word adaptable means that they provide necessary typedefs for being used in conjunction with standard function adaptors like std::not1, std::not2, std::bind1st, std::bind2nd.
When I need to use them?
You may use them every time you need to use your custom function object together with standard function adaptor.
Do you have an example?
Lets consider some examples (I know, they are artificial. From the other side I hope, that they are rather descriptive).
Example 1.
Suppose you want to print all strings in a vector with their lengths not less than a particular threshold and print them to std::cout.
One might use the next function object:
class LengthThreshold
{
public:
LengthThreshold(std::size_t threshold) : threshold(threshold) {}
bool operator()(const std::string& instance) const
{
return (instance.size() < threshold);
}
private:
const std::size_t threshold;
};
Now the task is pretty simple and can be performed by std::remove_copy_if algorithm:
// std::size_t threshold is defined somewhere
std::remove_copy_if(some_strings.begin(), some_strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
LengthThreshold(threshold)
);
What if you want to use the same function object to print all the strings with their lengths strictly less than the threshold?
The obvious solution we can come up with is the usage of std::not1 function adaptor:
// std::size_t threshold is defined somewhere
std::remove_copy_if(some_strings.begin(), some_strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
std::not1(LengthThreshold(threshold))
);
In fact, the code above won't compile because our LengthThreshold is not adaptable and has no typedefs which are necessary for std::not1.
To make it adaptable we need to inherit from std::unary_function:
class LengthThreshold : public std::unary_function<std::string, bool>
{
// Function object's body remains the same
}
Now our first example works like a charm.
Example 2.
Lets change our previous example. Suppose we don't want to store a threshold inside the function object. In such case we may change the function object from unary predicate to binary predicate:
class LengthThreshold : public std::binary_function<std::string, std::size_t, bool>
{
public:
bool operator()(const std::string& lhs, std::size_t threshold) const
{
return lhs.size() < threshold;
}
};
And make use of std::bind2nd function adaptor:
// std::size_t threshold is defined somewhere
std::remove_copy_if(some_strings.begin(), some_strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
std::bind2nd(LengthThreshold(), threshold)
);
What about C++11 and higher?
All the examples above intentionally use only C++ 03.
The reason is that std::unary_function and std::binary_function are deprecated since C++ 11 and completely removed from C++ 17.
It happened with the advent of more generalized and flexible functions like std::bind which make inheriting from std::unary_function and std::binary_function superfluous.

Using STL to bind multiple function arguments

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

Getting a vector<Derived*> into a function that expects a vector<Base*>

Consider these classes.
class Base
{
...
};
class Derived : public Base
{
...
};
this function
void BaseFoo( std::vector<Base*>vec )
{
...
}
And finally my vector
std::vector<Derived*>derived;
I want to pass derived to function BaseFoo, but the compiler doesn't let me. How do I solve this, without copying the whole vector to a std::vector<Base*>?
vector<Base*> and vector<Derived*> are unrelated types, so you can't do this. This is explained in the C++ FAQ here.
You need to change your variable from a vector<Derived*> to a vector<Base*> and insert Derived objects into it.
Also, to avoid copying the vector unnecessarily, you should pass it by const-reference, not by value:
void BaseFoo( const std::vector<Base*>& vec )
{
...
}
Finally, to avoid memory leaks, and make your code exception-safe, consider using a container designed to handle heap-allocated objects, e.g:
#include <boost/ptr_container/ptr_vector.hpp>
boost::ptr_vector<Base> vec;
Alternatively, change the vector to hold a smart pointer instead of using raw pointers:
#include <memory>
std::vector< std::shared_ptr<Base*> > vec;
or
#include <boost/shared_ptr.hpp>
std::vector< boost::shared_ptr<Base*> > vec;
In each case, you would need to modify your BaseFoo function accordingly.
Instead of passing the container object (vector<>), pass in begin and end iterators like the rest of the STL algorithms. The function that receives them will be templated, and it won't matter if you pass in Derived* or Base*.
This problem occurs in programming languages that have mutable containers. You cannot pass around a mutable bag of apples as a bag of fruit because you cannot be sure that someone else does not put a lemon into that bag of fruit, after which it no longer qualifies as a bag of apples. If the bag of apples were not mutable, passing it around as a bag of fruit would be fine. Search for covariance/contravariance.
one option is to use a template
template<typename T>
void BaseFoo( const std::vector<T*>& vec)
{
...
}
The drawback is that the implementation has to be in the header and you will get a little code bloat. You will wind up with different functions being instantiated for each type, but the code stays the same. Depending on the use case it's a quick and dirty solution.
Edit, I should note the reason we need a template here is because we are trying to write the same code for unrelated types as noted by several other posters. Templates allow you do solve these exact problems. I also updated it to use a const reference. You should also pass "heavy" objects like a vector by const reference when you don't need a copy, which is basically always.
Generally you would start with a container of base pointers, not the other way.
If you dealing with a third-party library, and this is your only hope, then you can do this:
BaseFoo (*reinterpret_cast<std::vector<Base *> *>(&derived));
Otherwise fix your code with one of the other suggesstions.
Taking Matt Price's answer from above, given that you know in advance what types you want to use with your function, you can declare the function template in the header file, and then add explicit instantiations for those types:
// BaseFoo.h
template<typename T>
void BaseFoo( const std::vector<T*>& vec);
// BaseFoo.cpp
template<typename T>
void BaseFoo( const std::vector<T*>& vec);
{
...
}
// Explicit instantiation means no need for definition in the header file.
template void BaseFoo<Base> ( const std::vector<Base*>& vec );
template void BaseFoo<Derived> ( const std::vector<Derived*>& vec );
If std::vector supported what you're asking for, then it would be possible to defeat the C++ type system without using any casts (edit: ChrisN's link to the C++ FAQ Lite talks about the same issue):
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
void pushStuff(std::vector<Base*>& vec) {
vec.push_back(new Derived2);
vec.push_back(new Base);
}
...
std::vector<Derived1*> vec;
pushStuff(vec); // Not legal
// Now vec contains a Derived2 and a Base!
Since your BaseFoo() function takes the vector by value, it cannot modify the original vector that you passed in, so what I wrote would not be possible. But if it takes a non-const reference and you use reinterpret_cast<std::vector<Base*>&>() to pass your std::vector<Derived*>, you might not get the result that you want, and your program might crash.
Java arrays support covariant subtyping, and this requires Java to do a runtime type check every time you store a value in an array. This too is undesirable.
They are unrelated types -- you can't.