I've looked at the top answers c++ to Visitor pattern and to pointers to member functions; but I still cannot get how the following (rather simple) scenario should be designed.
In a basic example, I want to have an optimizer class. Given a member function of another class, it find some optimal value. Something like this:
class Optimizer{
public:
typedef double (*Func1d)(double);
typedef double (*Func2d)(double,double);
void Optimize1d(Func1d* f1Ptr, double& x);
void Optimize2d(Func2d* f2Ptr, double& x, double& y);
};
and two example classes:
class A {
double A1d(double x){return x;}
};
class B{
double B2d(double x, double y){return x+y;}
};
and the main function, which I would like to be able to use as follows:
void main()
{
Optimizer opt;
double xA_opt, xB_opt, yB_opt;
opt.Optimize1d(&A::A1d,xA_opt);
opt.Optimize2d(&B::B2d, xB_opt, yB_opt);
}
But still, I can't get it to work. I don't want the optimizer to directly hold pointers to objects of type A and B; because then he needs to be familiar with these objects.
I hope this question makes sense. Thanks!
The problem is that typedef double (*Func1d)(double); is not a member-function-pointer but just a plain function-pointer.
If you used a real member-function-pointer, the function would also have to have an instance of A or B which you say you don't want.
If you can't make A1d and B2d static the other options are to make your Optimize1d and Optimize2d template functions taking a templated functor:
template<typename F>
void Optimize1d(F f1, double& x);
template<typename F>
void Optimize2d(F f2, double& x, double& y);
or a std::function:
void Optimize1d(std::function<double(double)> f1, double& x);
void Optimize2d(std::function<double(double, double)> f2, double& x, double& y);
Both can be called with a lambda capturing an instance of A or B:
A a;
B b;
opt.Optimize1d([&a](double x){return a.A1d(x); }, xA_opt);
opt.Optimize2d([&b](double x, double y){return b.B2d(x, y); }, xB_opt, yB_opt);
Edit:
If you don't have C++11 you could define your own functor using a class which defines an operator() instead of a lambda. The class will have to store a pointer or reference to an instance of A or B in a member variable:
struct A1d {
A* a;
A1d(A& a) : a(&a) {}
double operator()(double x) { return a->A1d(x); }
};
You can then construct an instance of this class and pass it to the templated optimize functions:
A1d a1d(a);
opt.Optimize1d(a1d,xA_opt);
Live demo.
perhaps you could even make your A or B classes functors themselves by adding an operator() function to them?
The problem in the above code is that in C++, pointer-to-member functions are a distinct type, incompatible with "regular" function pointers.
This typedef
typedef double (*Func1d)(double);
is legal in both C and C++ code, and you can use C-style "free" functions with this type.
But at this line in your main function:
opt.Optimize1d(&A::A1d,xA_opt);
you are trying to pass a pointer to member function as a Func1d and that can't be done. For one thing, you can't invoke a pointer to member function without a pointer to an object of that type as well, and you would have to pass that also.
The simplest thing is to include header <functional> and use std::function<double(double)> for this. (Assuming you have C++11, otherwise you could use boost::function.)
There are other things you could do like use virtual member dispatch as suggested in comments. (IMO that's a little less elegant.)
You could also make the optimize functions be template functions, and accept an object of the templated type etc. etc. But really std::function is the way to go here, it will handle all those details for you.
Related
How can I use a comparison function object type in a method signature? Eg., this is all fine:
struct compInt {
bool operator() (const int a, const int b) { return a < b; }
};
set<int,compInt> s1;
// Actually this is no good, but removing it would obfuscate
// the accepted answer:
set<int> s2(compInt);
[The last one compiles but it's a function declaration, s2 turns out not to be a container].
But I want to do this:
void func (____ x)
{
set<int> s(x);
}
I do not want to do this:
template<typename C>
void func (C& c)
{
set<int> s(c);
}
And function<bool(const int,const int)> does not work. I tried making compInt::operator() virtual so I could do this:
void func (compInt& ci)
And pass in derived objects, but in fact set<int> s(ci) then fails to compile (which I'm almost grateful for, because it is a horrid hack).
set<int> s1(compInt);
This declares a function whose return type is set<int>.
set<int> s(x);
This declares a local variable of type set<int>. The comparator type is not deduced from the argument, but instead the default template argument is used. As such, compInt is not used as the comparator, so you cannot pass an instance of compInt to the constructor.
You can use:
void func (compInt x)
{
std::set<int,compInt> s(x);
I tried making compInt::operator() virtual so I could do this:
void func (compInt& ci)
Polymorphic comparator would be quite problematic. Set stores the object by value, so passing into the function through a reference would not help. You would need to use type erasure: Define a wrapper comparator that takes a polymorphic comparator as constructor argument, stores it in dynamic storage, and delegates the call operator to the stored polymorphic comparator. Then use the wrapper type as the template argument of the set.
Eeroiki got me going in the right direction. What I eventually settled on was this (note the objects to be compared actually aren't ints, and a wide range of comparators could be applied to them).
using intCompFunc = std::function<bool(const int,const int)>
struct compInt {
intCompFunc comp;
bool operator() (const int a, const int b) const {
return comp(a, b);
}
void foo (intCompfunc icf)
{
compInt ci { icf };
std::set<int,compInt> s1(ci);
}
Which means the user can pass in any kind of functor, eg. a lambda:
foo([] (const int a, const int b) { return a < b; });
My confusion stems from why it isn't this way in the first place, which I think is really a historical problem (there were no C++11 functors when the STL was written). OTOH, using a base type instead of a template parameter does introduce some runtime overhead.
I have a class which has a few large fields (say, some big matrices) and has member functions to compute these matrices (the actual number of the matrices is bigger, of course)
class MyClass {
protected:
MatrixType m_11, m_12;
public:
void compute_m_11(double x);
void compute_m_12(double x);
}
Now, the computation code is very similar, and the most complex part is correct indexing of the matrix elements (which is the same for all the matrices involved). So I was thinking about splitting the indexing and the computation into separate functions: a compute_matrix function which will perform the indexing and call a compute_element function for each set of indexes in the matrix. This would greatly improve code readability and ease debugging.
So the compute_matrix function would take a MatrixType reference to the class field which I need to fill in and a std::function which would perform the actual computation. I obviously want to avoid writing anything that will involve additional copying of the matrices, since they can be quite large.
So, the questions are:
Is it legal/efficient to pass a reference to a class field to a class member function?
If so, do I need to use std::bind to pass the computation member functions? The compute_elements functions need to access some other fields of MyClass.
This is what I have in mind:
class MyClass {
protected:
MatrixType m_11, m_12;
double compute_elements_m11(int i, int j, double x);
double compute_elements_m12(int i, int j, double x);
void compute_matrix(MatrixType &m, double x, std::function<double(int, int, double) > f);
public:
void compute_m_11(double x) {compute_matrix(m_11, x, compute_elements_m11);};
void compute_m_12(double x) {compute_matrix(m_12, x, compute_elements_m12);};
}
It is legal (and not that uncommon) to pass a member reference, but your function type is wrong.
You could use std::bind, or you could use a plain pointer-to-member:
class MyClass {
protected:
MatrixType m_11, m_12;
double compute_elements_m11(int i, int j, double x);
double compute_elements_m12(int i, int j, double x);
void compute_matrix(MatrixType &m, double x, double (MyClass::*f) (int, int, double);
public:
void compute_m_11(double x) {compute_matrix(m_11, x, &MyClass::compute_elements_m11);};
void compute_m_12(double x) {compute_matrix(m_12, x, &MyClass::compute_elements_m12);};
};
std::bind and std::function gives a more flexible implementation though.
Sure it's not uncommon to pass a class attribute to an internal member function and you can also use std:bind to call the member function, but the question is do you really need that or can you just use a simple "if" or something similar to decide what to use? I'd say it depends on how many choices your code path has to decide that better.
Why would you pass a reference to a class field to a class member function? A better solution would be to implement a get method and use that in the compute_matrix function. Your class will then look something like this:
class MyClass {
protected:
MatrixType m_11, m_12;
double compute_elements_m11(int i, int j, double x);
double compute_elements_m12(int i, int j, double x);
void compute_matrix(double x, std::function<double(int, int, double) > f);
public:
void compute_m_11(double x) {compute_matrix(x, compute_elements_m11);};
void compute_m_12(double x) {compute_matrix(x, compute_elements_m12);};
MatrixType& getMatrixType_11( return m_11 );
MatrixType& getMatrixType_12( return m_12 );
}
Hi I am trying to get to grips with functors. Here is a simple example
struct A {
double b,c;
A(const double bb, const double cc) : b(bb), c(cc) {}
double operator()(const double x, const double y) {
return b*c*x*y;
}
};
I would like to know if it is possible to overload A such that it could be passed b, c and also e.g. x reusing the code in the operator(). My overall interest is to not have to re-write lengthy code in operators multiple times and to better understand the best practices for doing this.
Thanks!
I would like to know if it is possible to overload A such that it could be passed b, c and also e.g. x reusing the code in the operator().
Yes, it is not difficult to do that.
double operator()(double x, double y) // Remove the const. It's useless.
{
// Call the other overload using the member data.
return (*this)(b, c, x, y);
}
double operator()(double bb, double cc, double x, double y)
{
// Not using any member data at all.
return bb*cc*x*y;
}
One method of doing this is with std::bind in <functional>. This returns a closure that you can call without arguments. An alternative would be to create a new constructor with default arguments for a and b, or a derived class, and overload it to have:
double operator()(const double x = m_x, const double y = m_y);
As a side note, please don't use the same names for members and arguments of member functions; that creates ambiguity about which you mean and could even cause bugs if you rename a parameter later.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Why does the following compiles i.e. passing a free function as parameter with the right signature:
inline double free_adapter_f(unsigned n, const double *x, double *grad, void *d) {
return 0.0;
}
nlopt::opt opt(nlopt::LN_NELDERMEAD, X.size());
opt.set_min_objective(free_adapter_f, NULL);
whereas this other doesn't compile i.e. passing the result of boost::bind a class member function with the same signature:
template<class Space, class Solution, class Oracle>
inline double NelderMead<Space, Solution, Oracle>::adapter_f(unsigned n, const double *x, double *grad, void *d) {
return 0.0;
}
nlopt::opt opt(nlopt::LN_NELDERMEAD, X.size());
opt.set_min_objective(boost::bind(&NelderMead::adapter_f, this, ::_1, ::_2, ::_3, ::_4), NULL);
The error message is the following:
nelder_mead.h(98): error: no instance of overloaded function "nlopt::opt::set_min_objective" matches the argument list
argument types are: (boost::_bi::bind_t<double, boost::_mfi::mf4<double, NelderMead<TestSpace, VectorXd, oracle_f>, unsigned int, const double *, double *, void *>, boost::_bi::list5<boost::_bi::value<NelderMead<TestSpace, VectorXd, oracle_f> *>, boost::arg<1>, boost::arg<2>, boost::arg<3>, boost::arg<4>>>, long)
object type is: nlopt::opt
opt.set_min_objective(boost::bind(&NelderMead::adapter_f, this, ::_1, ::_2, ::_3, ::_4), NULL);
UPDATE: the overloaded set_min_objective are:
typedef double (*func)(unsigned n, const double *x, double *grad, void *f_data);
typedef double (*vfunc)(const std::vector<double> &x, std::vector<double> &grad, void *f_data);
void set_min_objective(func f, void *f_data);
void set_min_objective(vfunc vf, void *f_data);
You need to define set_min_objective which accepts boost::function as first parameter:
typedef boost::function<double (unsigned n, const double *x, double *grad, void *f_data)> func_t;
...
void set_min_objective(func_t, void*);
...
another thing - you'd better not to use NULL
Here is a simple example, which demonstrates your problem:
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
namespace g
{
typedef int (*func)(int a, int b, int c);
void bar(func f)
{
std::cout << "g::bar:: called" << (*f)(10, 20, 30) << std::endl;
}
// Disable the over load below and you will get the same error
void bar(boost::function<int(int, int, int)> f)
{
std::cout << "g::bar:: called" << f(10, 20, 30) << std::endl;
}
}
template <typename A, typename B, typename C>
class foo
{
public:
int bar(int a, int b, int c) const
{ return a + b + c; }
void call()
{
g::bar(boost::bind(&foo::bar, this, ::_1, ::_2, ::_3));
}
};
int main(void)
{
foo<int, double, int> f;
f.call();
return 0;
}
Main reason is that boost::function<> is not convertible to a function pointer, so you need to provide an overload which accepts this (as above.)
EDIT: just to clarify things a little further. boost::bind() does not explicitly return a boost::function<>, however, the object it returns can be stored in the correct instantiation of boost::function<>, in the above case, the correct instantiation is boost::function<int(int, int, int)>.
Normally you would only need to resort to storing it in a boost::function if you were interested in propagating it (without a template) or storing it for later use. In this case, as you are passing the result of the bind(), you need to have the correct overload to accept the returned object from boost::bind(), and the easiest way to do this without resorting to templates is to accept a boost::function (as above.)
Normally, I'm pragmatic, so I would resort to this (without knowing what you are wanting to do with f) where possible.
template <typename F>
double set_min_objective(F f, ...)
{
}
Then you are agnostic, of course purists will have other opinions.
NOTE: A nice thing with boost::function<> is that you can store a non-member function pointer in one too (as long as the signature matches.) So in reality you only need a version of your function which accepts the correct boost::function<> and it will work in both cases (member function with boost::bind() and non-member function.)
EDIT2: Okay, given the additional information, you have to resort to the following mechanism, you need to have a non-member function of your class, which will then delegate to the member function, for example:
<>
class NelderMead
{
static double delegate_f(unsigned n, const double *x, double *grad, void *f_data)
{
// I'm assuming here the frame work passed you whatever you gave in f_data
NelderMead* inst = reinterpret_cast<NelderMead*>(f_data);
return inst->adapter_f(n, x, grad);
}
double adapter_f(unsigned n, const double *x, double *grad)
{
}
void set()
{
nlopt::opt opt(nlopt::LN_NELDERMEAD, X.size());
opt.set_min_objective(delegate_f, this); //<-- here pass the instance as the additional data
}
};
This is a typical pattern employed by third-party libraries which are meant to be agnostic to user code.
Both overloads of set_min_objective expect a pointer-to-function as the first parameter, but the object returned by boost::bind is not a pointer-to-function, it's a function object.
boost::bind returns a function object that stores the target function and any bound arguments, it doesn't synthesize a function and return a pointer to it, or magically turn a pointer-to-member-function into a pointer-to-function. That would be magic.
This is a functor:
class add_x {
int x;
public:
add_x(int x) : x(x) {}
int operator()(int y) { return x + y; }
};
And from main I can do this:
add_x add10(10); // create my functor
int i = add10(20); // add 20 and return it
How can I combine the functor with typedef?
For instance, I came across this:
typedef int (*myfuncType)(float f, char c1,char c2);
myfuncType pt2Function = NULL;
But what am I defining here exactly? operator ()?
Function pointer is - as its name says - just a pointer to function. You cannot use a pointer to function to point to functor, which is essentially a class with overloaded () operator.
You may be interested in std::function from C++11:
#include <functional>
(...)
std::function<int(int)> fn = add_x(10);
int i = fn(20);
Edit: Ok, I see, what you are asking for.
Maybe some code will make things clear.
int fn(float a, char b, char c) { ... }
(...)
typedef int (*myFuncType)(float f, char c1, char c2);
myFuncType ptrToFun = &fn;
(*fn)(1.0f, 'a', 'z');
This typedef creates a "pointer-to-function" type. If you declare a variable of this type, then you'll be able to assign to it a pointer to function (extracted with regular & operator) and - for example - pass to another function or just store (or call this function).
std::function is a lot more flexible, because you can store in it a pointer to function, a functor or even a lambda and call them normally.
I don't understand your first question (How can I combine the functor with typedef ?), so I can't answer that - a typedef would work as it would with any other class.
Regarding your second question: the line
typedef int (*myfuncType)(float f, char c1,char c2);
gives a name (myfunctType) to the type int (*)(float, char, char) (read: "a function which takes a float and two char values and then returns an int").
So
myfuncType pt2Function = NULL;
Defines a variable which can point to such an above-mentioned function, but sets the pointer to NULL for now.
Here, myfuncTypeis a type describing a pointer of function, with three float parameters and which return an int. A functor is just a class with operator() overload. So the typedef is used just like other class.
typedef add_x add will work.