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.
Related
I am trying to do the following, and I am not even sure if it's possible.
I want a function that takes in an arbitrary function pointer to pass it to a different function (I am aware this is a code smell, good software engineering practices are not what I want to discuss right now).
In other words what I am looking for would look like:
void method1(arbitraty pointer p)
{
method2(p);
}
I am not sure if there is a way to declare arbitrary function pointers (the return value is guaranteed to be void but the parameters are arbitrary, both in number and type)
Use template and use SFINAE to enable it only if the type deduced is a function pointer type:
template <typename T, std::enable_if_t<std::is_function<T>::value, int> = 0>
void method1(T* p)
{
// ...
}
This might be considered over-engineering by some, but you could try the following:
Create an enum of each callback that you are interested in:
enum GlfwCallback {
KeyCallback,
FramebufferSizeCallback,
// etc.
};
Then create a type family that associates each of these with the corresponding function pointer type. Do this by creating a template struct and repeatedly specializing it:
template<GflwCallback callback>
struct GlfwCallbackType {};
template<>
struct GlfwCallbackType<KeyCallback> {
using CallbackType = GLFWkeyfun;
// or
using CallbackType = void(*)(GLFWwindow *, int, int, int, int);
};
template<>
struct GlfwCallbackType<FramebufferSizeCallback> {
using CallbackType = GLFWframebuffersizefun;
};
// etc.
Then you can write
template<GlfwCallback callback>
void method1(GlfwCallbackType<callback>::CallbackType p) {
// do something with p
method2<callback>(p);
};
Also, note that you can add other types and even static functions and data members to your "type family" as needed by your application.
A possibility to do what you want, but in a nice, type-safe fashion, would be the use of functors, i.e. classes that define an overloading for the operator().
Since a functor is a class, you could set the arguments as data memebers, and move the implementation/calling of the functions that you want to pass as arbitrary pointers into the operator() method, where you can have access to all the parameters through the this pointer.
Furthermore, you can define a hierarchy of functors, each one with specialized parameters and implementations, so you can modify the signature of method2 like the following:
method2(BaseFunctor* myfunctor) {
if (myfunctor)
(*myfucntor)();
}
and setup the right type of functor object in the calling context.
Also check out lambdas (c++11), that are basically a shortcut to functors definition.
I'm using template functions for object construction to create objects from reflection data, and it works pretty well, but now I want to support STL container types in the reflection system so that objects such as:
// Note - test case only
// for real world usage it would probably not be structured like this
// and the phrases would be mapped by an id or something
struct Phrases {
std::vector<std::string> phrases;
};
typedef std::string Lang;
struct Langs {
std::map< Lang, Phrases > translations;
};
Can be supported. I can do some regex magic on the return of
typeid( object ).name()
to figure out if an object is a vector or a map, and what the parameter arguments for the object is. And I have tried some template magic to do it something like the following, where CreateString, ConstructString & DestroyString are stand in functions and the data is stand in as well for something a bit more complex that uses a type database to handle object construction.
// Representational of code, basically a copy-paste to a different test project where I can work out the problems with this specific vector problem
// Vector specialised construction
template <typename T> void ConstructVector( void* object, const std::vector<std::string>& data ) {
T* vec = (T*)object;
Name vector_type = GetVectorTypeName<T>();
void *obj;
CreateString(&obj);
// All fields in this type should be valid objects for this vector
for( std::vector<std::string>::const_iterator it = data.begin(), end = data.end(); it != end; ++it ) {
// Push it
vec->push_back(*obj);
// Get address to new instance
void *newly = &vec->back();
ConstructString(newly,*it);
}
DestroyString(&obj);
}
Which doesn't work owing to the illegal indirection with "vec->push_back(*obj);" which I can't case because I don't actually know the type. Basically what I need to be able to do is create this vector with some blank unset elements already in it, or add new elements to it without actually having the type, because if I can get a pointer to a memory block inside the vector I can roll with that and construct the object. But the vector add requirements such as
vector::push_back( T& value )
or
vector::insert( Iter&, T& )
Won't work for me unless I can get my hands on that T type from inside the template
pastebin of testing code to try and solve this:
http://pastebin.com/1ZAw1VXg
So my question is, how can I get the std::string part of a std::vector declaration when I'm inside a template like
template <typename T> void SomeFunc() {
// Need to get std::string here somehow
// Alternatively need to make the vector a certain size and then
// get pointers to it's members so I can construct them
}
SomeFunc<std::vector<std::string>>>();
There are two ways to accomplish this.
1) Either you make use of the fact that std::vector<> (like all standard library container classes) maintains a member type value_type, which represents the type of the elements stored in the vector. So you can do this:
template <typename T> void SomeFunc() {
typename T::value_type s; // <--- declares a `std::string` object
// if `T` is a `std::vector<std::string>`
}
2) Or else, you change the declaration of your function and make use of template template parameters:
template <template <typename> class T, typename Elem>
void SomeFunc(T<Elem> &arg)
{
Elem s;
}
However, there is a small problem with that: std::vector is really a template with two parameters (element type and allocator type), which makes it a little difficult to use the template template parameters and still keep the syntax simple. One thing that worked for me is to declare an alias of the vector type that leaves only one template parameter:
template <typename Elem>
using myvector = std::vector<Elem>;
Then I can use SomeFunc like this:
int main()
{
myvec<std::string> vec;
SomeFunc(vec);
}
In c++11, you can use decltype and std::decay to that effect:
std::vector<int> vec;
using T = typename std::decay<decltype(*vec.begin())>::type;
I'm new to std::generate and have attempted to structure a program which uses it to initialize vectors. However it's behaving differently to my expectations.
I have an abstract base class:
template <typename G>
class RandomAllele {
public:
RandomAllele() { /* empty */ }
virtual ~RandomAllele() { /* empty */ }
virtual G operator()() const = 0;
};
Which is extended by (for example):
class RandomInt : public RandomAllele<int> {
public:
RandomInt(int max) : max_(max) {}
int operator()() const { return rand() % max_; }
private:
int max_;
};
I pass an instance of my inheriting class to a factory class by pointer, and then use it as the third argument for std::generate:
template<typename G, typename F>
class IndividualFactory {
public:
IndividualFactory(int length, const RandomAllele<G> *random_allele)
: length_(length), random_allele_(random_allele) { /* empty */ }
individual_type *generate_random() const {
std::vector<G> *chromosome = new std::vector<G>(length_);
std::generate(chromosome->begin(), chromosome->end(), *random_allele_); */
return new individual_type(chromosome);
}
private:
int length_;
RandomAllele<G> *random_allele_;
};
Now I get an error saying that RandomAllele cannot be instantiated because it's an abstract class. Why does generate need to instantiate it when the pointer already exists? And why is it trying to use the base class instead of the inheriting class RandomInt?
This works fine if I replace std::generate with:
for(auto iter = chromosome->begin(); iter != chromosome->end(); ++iter)
*iter = (*random_allele_)();
But I still wish to understand why it behaves strangely, and I'd prefer to use generate if there is a way to do this.
Thanks for your time,
Rhys
As others have mentioned above, the generate and generate_n functions take their generator objects by value, precluding you from directly using inheritance in this context.
However, one trick you can do is to apply the Fundamental Theorem of Software Engineering:
Any problem can be solved by adding another layer of indirection
Rather than directly passing in a polymorphic functor, instead pass in a wrapper functor that stores a pointer to this polymorphic functor and then forwards the call appropriately. For example:
template <typename T> class IndirectFunctor {
public:
explicit IndirectFunctor(RandomAllele<T>* f) : functor(f) {
// Handled in initializer list
}
T operator() () const {
return (*functor)();
}
private:
RandomAllele<T>* functor;
};
If you then pass this object into generate, as seen here:
RandomAllele<T>* functor = /* ... create an allele ... */
std::generate(begin, end, IndirectFunctor<T>(functor));
Then everything will work as intended. The reason for this is that if you copy IndirectFunctor<T> by value, then you just shallow-copy the stored pointer, which will still point to the RandomAllele you want to call. This avoids the slicing problem you were encountering because it never tries directly copying an object of type RandomAllele through a base class pointer. It always copies the wrapper object, which never tries to duplicate RandomAllele.
Hope this helps!
std::generate's generator is passed by value, and therefore copied.
In general the C++ standard library implements static polymorphism (templates) and doesn't support runtime polymorphism (virtual methods) for function objects. This is because it passes all its function objects by values, assuming them to be stateless or almost stateless such that the added indirection of passing by pointer or reference would be more expensive than by value.
Since it's passed by value this results in slicing and when you try to use a RandomAllele<G> it thinks you mean that exact class not whatever derived type it actually points to. Instead of templating on G just template on the exact generator functor type you desired directly.
The issue is that all standard algorithms take their arguments by value, to conform with traditional C constraints. So here the std::generate() algorithm take the functor by value. Your functor, of type RandomAllele<int>, is of abstract type. Yes, it's a pointer pointing at a concrete type, but the pointer is of an abstract type. In copying this object, the algorithm calls the copy constructor of RandomAllele<int>; i.e., the algorithm constructs an instance of abstract type. And this is something the C++ language forbids.
You can tell the runtime environment not to worry too much like so:
RandomInt *cp = dynamic_cast<RandomInt*>(random_allele);
if( ! cp ) {
// i thought the pointer is of RandomInt. It isn't. Err.
std::terminate(); // or something
}
std::generate(chromosome->begin(), chromosome->end(), *cp);
The prototype is:
template <class ForwardIterator, class Generator>
void generate ( ForwardIterator first, ForwardIterator last, Generator gen );
Hence gen is passed by value, so the compiler attempts to construct a RandomAllele by copy, hence problem.
The solution is to use an Envelope to provide the needed indirection:
template<class G>
class RandomAlleleEnvelope
{
public:
RandomAlleleEnvelope(const RandomAllele<G>* ra)
: ra_(ra)
{}
int operator()() const { return (*ra_)(); }
private:
const RandomAllele<G>* ra_;
};
std::generate<std::vector<int>::iterator,RandomAlleleEnvelope<int> >(chromosome->begin(), chromosome->end(), random_allele_);
Also note there is another solution, define your own generate to use a reference:
template <class ForwardIterator, class Generator>
void referenceGenerate ( ForwardIterator first, ForwardIterator last,
const Generator& gen )
{
while (first != last) *first++ = gen();
}
referenceGenerate(chromosome->begin(), chromosome->end(), *random_allele_);
I also think the following should work, that is to use the standard generate and explicitly make it handle a reference type:
std::generate<std::vector<int>::iterator, const RandomAllele<int>& >
(chromosome->begin(), chromosome->end(), *random_allele_);
I say should because this fails is instantiate on VS2010. On the other hand, if I can define my own:
template <class ForwardIterator, class Generator>
void myGenerate ( ForwardIterator first, ForwardIterator last, Generator gen )
{
while (first != last) *first++ = gen();
}
myGenerate<std::vector<int>::iterator, const RandomAllele<int>& >
(chromosome->begin(), chromosome->end(), *random_allele_);
The VS2010 fails because it implements std::generate is terms of another std::generate which defaults back to non-reference parameters.
I need a function which establishes a policy for my class for displaying items. e.g:
SetDisplayPolicy(BOOLEAN_PRED_T f)
This is assuming BOOLEAN_PRED_T is a function-pointer to some boolean predicate type like:
typedef bool (*BOOLEAN_PRED_T) (int);
I'm interested only on e.g: display something when the passed predicate is TRUE, do not display when it's false.
The above example works for functions returning bool and taking an int, but I need a very generic pointer for the SetDisplayPolicy argument, so I thought of UnaryPredicate, but it's boost related. How I can pass a unary predicate to a function in STL/C++? unary_function< bool,T > won't work because I need a bool as return value, but I want to ask the user just for "unary function that returns bool", in the most generic approach.
I thought of deriving my own type as:
template<typename T>
class MyOwnPredicate : public std::unary_function<bool, T>{};
Could that be a good approach?
Turn SetDisplayPolicy into a function template:
template<typename Pred>
void SetDisplayPolicy(Pred &pred)
{
// Depending on what you want exactly, you may want to set a pointer to pred,
// or copy it, etc. You may need to templetize the appropriate field for
// this.
}
Then to use, do:
struct MyPredClass
{
bool operator()(myType a) { /* your code here */ }
};
SetDisplayPolicy(MyPredClass());
In the display code you would then d someting like:
if(myPred(/* whatever */)
Display();
Of course, your functor may need to have a state and you may want its constructor to do stuff, etc. The point is that SetDisplayPolicy doesn't care what you give it (including a function pointer), provided that you can stick a function call onto it and get back a bool.
Edit: And, as csj said, you could inherit from STL's unary_function which does the same thing and will also buy you the two typedefs argument_type and result_type.
You're on the right track since unary_function is intended as a base class. However, note that the first parameter is supposed to be the argument_type and the second is the result_type. Then, all you need to do is implement operator()
template<typename T>
struct MyOwnPredicate : public std::unary_function<T,bool>
{
bool operator () (T value)
{
// do something and return a boolean
}
}
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%