I am trying to avoid this repetitive code by writing a template function.
#include <algorithm>
class X {
public:
void get_amin(double *a){}
void set_amin(double a){}
void get_bmin(double *b){}
void set_bmin(double b){}
//...many pairs like above
};
int main(){
X *x1 = new X;
X *x2 = new X;
//code that will be repeated
{
double x1_amin;
x1->get_amin(&x1_amin);
double x2_amin;
x2->get_amin(&x2_amin);
x1->set_amin(std::min(x1_amin, x2_amin));
}
//repeatation
{
double x1_bmin;
x1->get_bmin(&x1_bmin);
double x2_bmin;
x2->get_bmin(&x2_bmin);
x1->set_bmin(std::min(x1_bmin, x2_bmin));
}
//
delete x1;
delete x2;
}
Now my attempts are below. It seems I am able to write the template but not able to use it. Other posts at stack overflow mostly focus on how to write the template. Also I could not find an example where a class member function is used.
#include <algorithm>
#include <functional>
class X {
public:
void get_amin(double *a){}
void set_amin(double a){}
void get_bmin(double *b){}
void set_bmin(double b){}
//...many pairs like above
};
template <typename F11,typename F12, typename F2>
void templatisedFunction(F12 f11,F12 f12,F2 f2)
{
double x1_amin;
f11(&x1_amin);
double x2_amin;
f12(&x2_amin);
f2(std::min(x1_amin, x2_amin));
}
int main(){
X *x1 = new X;
X *x2 = new X;
//templatisedFunction(x1->get_amin,x2->get_amin,x1->set_amin);
//templatisedFunction(x1->get_amin(double*),x2->get_amin(double*),x1->set_amin(double));
//templatisedFunction<x1->get_amin(double*),x2->get_amin(double*),x1->set_amin(double)>();
//templatisedFunction<x1->get_amin,x2->get_amin,x1->set_amin>();
std::function<void(X*)> memfun(&X::get_amin);//not sure here
//templatisedFunction<x1->get_amin,x2->get_amin,x1->set_amin>();
//
delete x1;
delete x2;
}
void (X::*getf)(double *) and void (X::*setf)(double) are the function signatures for the two pointer to member function that you need.
Using C++11:
int main()
{
X x1;
X x2;
auto lamb = [&](void (X::*getf)(double *), void (X::*setf)(double))
{
double x1_amin;
(x1.*getf)(&x1_amin);
double x2_amin;
(x2.*getf)(&x2_amin);
(x1.*setf)(std::min(x1_amin, x2_amin));
};
lamb(&X::get_amin, &X::set_amin);
lamb(&X::get_bmin, &X::set_bmin);
return 0;
}
You can use pointers to member functions to reduce repetition:
void set_min(X &x1, X &x2, void (X::*get_min)(double *), void (X::*set_min)(double)) {
double x1_amin;
(x1.*get_min)(&x1_amin);
double x2_amin;
(x2.*get_min)(&x2_amin);
(x1.*set_min)(std::min(x1_amin, x2_amin));
}
to be used like this:
set_min(*x1, *x2, &X::get_amin, &X::set_amin);
set_min(*x1, *x2, &X::get_bmin, &X::set_bmin);
If you have many pairs you could go even further and use a loop:
std::pair<void (X::*)(double *), void (X::*)(double)> get_set_pairs[] = {
{&X::get_amin, &X::set_amin},
{&X::get_bmin, &X::set_bmin},
};
for (auto &get_set_pair : get_set_pairs){
set_min(*x1, *x2, get_set_pair.first, get_set_pair.second);
}
Related
I have to solve, at least for me, a tricky problem in C++. There is a dll which i can not modify. It gets a function pointer as argument. If I pass a pointer to a global function everything works fine. Unfortunatelly there is a list of same class objects to pass to the dll. In C# I solved this by using delegates. How can this be done in C++? Using std::function does not work. With that there are coding convention errors during runtime. Further using MSVC2010 would be optimal.
I wrote a sample which describes the problem:
#include <stdio.h>
// global function which works
void __stdcall task_global(float x, float y) { printf("Called global function with: %f %f\n", x, y); }
typedef void(__stdcall *f_pointer)(float, float);
// try of using a member function
class BaseTask {
public:
virtual void __stdcall task(float x, float y) = 0;
};
class ListeningTask :public BaseTask {
public:
void __stdcall task(float x, float y) { printf("Called this member function with: %f %f\n", x, y); }
};
typedef void (BaseTask::*member_f_pointer)(float, float);
// the dll to use
class RegisterTask {
public:
// no posibility to access or modify!
void __stdcall subscribe(f_pointer fp) { fp(1.0f, 2.0f); }
// just for demonstration how to use a member function pointer
void __stdcall subscribeMemberDemo(member_f_pointer mfp) { /*how to use mfp?*/};
};
int main() {
RegisterTask register_task{};
// use global function
f_pointer pointer_to_global_task = task_global;
register_task.subscribe(pointer_to_global_task);
/*---------------------------------------------------------------*/
// use member function?
std::list<ListeningTask> listening_task_list;
for(int i = 0; i < 10; i++) {
listening_task_list.push_back(ListeningTask lt);
member_f_pointer pointer_to_member_task = &listening_task_list.back().task; //error C2276: '&': illegal operation on bound member function expression
register_task.subscribeMemberDemo(pointer_to_member_task);
// the tricky and important one to solve
// how to pass the member function to this subscribe(f_pointer)?
register_task.subscribe(pointer_to_member_task);
}
getchar();
return 0;
}
The important question is how to pass a member function pointer to the RegisterTask::subscribe(f_pointer)?
The parenthetic question is how to pass a member function to the RegisterTask::subscribeMemberDemo(member_f_pointer)?
I hope someone can help me to solve this? I am working on this since days.
Edit:
I modified the question to emphasize the problem with the list of ListenerTask. How to pass a member function pointer is now clear to me through the answers of #pokey909 and #AndyG. Both of them provide a pointer to one object or rather a list of objects. If the callback is called the one ListenerTask or all std::list<*ListenerTask> are called at once. But how to let only one ListenerTask of the list to be called. Passing more than one callback to the dll. It (RegisterTask) can do that, because the following example with global functions works.
void __stdcall task_global_1(float x, float y) { printf("Called global function 1 with: %f %f\n", x, y); }
void __stdcall task_global_2(float x, float y) { printf("Called global function 2 with: %f %f\n", x, y); }
void __stdcall task_global_3(float x, float y) { printf("Called global function 3 with: %f %f\n", x, y); }
typedef void(__stdcall *f_pointer)(float, float);
int main() {
// give the functions to the dll.
f_pointer pointer_to_global_task_1 = task_global_1;
register_task.subscribe(pointer_to_global_task_1);
f_pointer pointer_to_global_task_2 = task_global_2;
register_task.subscribe(pointer_to_global_task_2);
f_pointer pointer_to_global_task_3 = task_global_3;
register_task.subscribe(pointer_to_global_task_3);
}
There are three global function pointers. They are all given to the dll. Now, if the dll has a task for task_global_2 it notifies this only! How to achive this distinction with member function pointer?
Note:
I got the source of the dll. Hope this helps. Unfortunately modifying, building is not possible. Here is the callback definition:
type TCallback = procedure( x : single; y : single; ); stdcall;
procedure subscribe(aCallback: TCallback ); StdCall;
begin
TaskSocket.addTask( aCallback );
end;
procedure TSocket.addTask( aCallback : TCallback);
var newTask : TTask;
begin
newTask := TTask.Create(aCallback);
TaskList.addItem(newTask);
end;
You can use a freestanding function that calls a wrapper which binds your instance to it.
Here is rough example
#include <iostream>
#include <string>
#include <functional>
// global function which works
std::function<void(float, float)> memberCb;
void task_global(float x, float y) { memberCb(x, y); }
typedef void(*f_pointer)(float, float);
// try of using a member function
class BaseTask {
public:
virtual void task(float x, float y) = 0;
};
class ListeningTask :public BaseTask {
public:
void task(float x, float y) { printf("Called this member function with: %f %f\n", x, y); }
};
typedef void (BaseTask::*member_f_pointer)(float, float);
void callbackWrapper(BaseTask* t, float x, float y) { t->task(x, y); }
// the dll to use
class RegisterTask {
public:
// no posibility to access or modify!
void subscribe(f_pointer fp) {
fp(1.0f, 2.0f);
}
// just for demonstration how to use a member function pointer
void subscribeMemberDemo(member_f_pointer mfp) { /*???*/ };
};
int main() {
RegisterTask register_task{};
ListeningTask listening_task{};
memberCb = std::bind(&callbackWrapper, &listening_task, std::placeholders::_1, std::placeholders::_2);
register_task.subscribe(task_global);
return 0;
}
Note
Based on the comment, I'm not sure if all of this works in MSVC2010, since I don't have this compiler version. But rudimentary C++11 support should be in there.
Edit
I'm not sure if thats what you are after, but would this solve your problem?
void callbackWrapper(const std::list<BaseTask*> &taskList, float x, float y) {
for (auto t : taskList)
t->task(x, y);
}
int main() {
RegisterTask register_task{};
std::list<BaseTask*> taskList;
for (int i = 0; i < 4; ++i)
taskList.push_back(new ListeningTask);
memberCb = std::bind(&callbackWrapper, taskList, std::placeholders::_1, std::placeholders::_2);
register_task.subscribe(task_global);
return 0;
}
Edit 2
Ok I think I got what you want. The best I can come up with without splattering your code with global functions manually is with template magic.
Note however, that it is not as flexible as you might want because you have to bind those methods at compile time.
If you need to add them at runtime, you can probably use the same trick but without templates. Simply put all the std::function objects in a vector and wrap that up in a singleton or something similar.
#include <iostream>
#include <string>
#include <functional>
#include <list>
/* Simulated DLL */
typedef void(*f_pointer)(float, float);
class RegisterTask {
public:
void subscribe(f_pointer fp) {
fp(1.0f, 2.0f);
}
};
/* Static function generator to ease the pain to define all of them manually */
template<unsigned int T>
std::function<void(float, float)> &getWrapper() {
static std::function<void(float, float)> fnc;
return fnc;
}
/* Same here */
template<unsigned int T>
void task_global(float x, float y) { getWrapper<T>()(x, y); }
class BaseTask {
public:
virtual void task(float x, float y) = 0;
};
class ListeningTask :public BaseTask {
public:
ListeningTask(int taskNum) : m_taskNum(taskNum) {}
void task(float x, float y) { printf("Called this member of task %d function with: %f %f\n", getTaskNum(), x, y); }
int getTaskNum() const { return m_taskNum; }
private:
int m_taskNum;
};
/* Context injector */
void callbackWrapper(BaseTask* t, float x, float y) {
t->task(x, y);
}
/* Convenience function to bind an instance to a task */
template<unsigned int T>
void bindTask(ListeningTask* t) {
getWrapper<T>() = std::bind(&callbackWrapper, t, std::placeholders::_1, std::placeholders::_2);
}
int main() {
RegisterTask register_task{};
auto task0 = new ListeningTask(1337);
auto task1 = new ListeningTask(1984);
auto task2 = new ListeningTask(42);
bindTask<0>(task0);
register_task.subscribe(task_global<0>);
bindTask<1>(task1);
register_task.subscribe(task_global<1>);
bindTask<2>(task2);
register_task.subscribe(task_global<2>);
return 0;
}
Run Code demo
pokey909's answer is totally great, but if you don't even have access to std::function and std::bind, we can hack our way around it.
The gist of the approach is that we are going to define a template class with an implicit conversion to the desired function type. The downside is that each new additional wrapper requires a new type declaration.
// assumes two function arguments
template<class Ret, class Mem, class Arg1, class Arg2, int>
struct MemBind
{
typedef Ret(Mem::*mem_fn_type)(Arg1, Arg2);
static void Set(mem_fn_type _fn, Mem* _instance)
{
fn = _fn;
instance = _instance;
}
static Ret DoTheThing(Arg1 first, Arg2 second)
{
return ((*instance).*fn)(first, second);
}
typedef Ret(*fn_type)(Arg1, Arg2);
operator fn_type ()
{
return DoTheThing;
}
static mem_fn_type fn;
static Mem* instance;
};
Given some struct Foo with our desired callback:
struct Foo
{
void Bar(float a, float b)
{
std::cout << "Foo::Bar(float, float) " << a << " , " << b << std::endl;
}
};
We have to define our static members:
typedef MemBind<void, Foo, float, float, 0> MemBindZero;
template<> Foo* MemBindZero::instance = nullptr;
template<> void(Foo::*MemBindZero::fn)(float, float) = nullptr;
We can have a caller that takes in a function pointer:
void Caller(void(*_fn)(float, float))
{
_fn(42.0, 1337.0);
}
The key here is that MemBind has an implicit conversion to the desired function type. The 0 in the typedef for MemBindZero allows us to re-use the same types for the other arguments, but increment the counter to 1 when used. I think you could probably replace it with a __COUNTER__ macro or something like that, but it would be nonstandard so I did it manually.
Now the next bit is to create an instance of MemBindZero, then set the static members, and finally pass our instance into Caller:
Foo f;
MemBindZero bound;
bound.Set(&Foo::Bar, &f);
Caller(bound);
Demo
In the demo I wrapped the static member initialization into a more convenient macro:
#define MEMBIND(RET, CLASS, ARG1, ARG2, COUNT, ALIAS) \
typedef MemBind<RET, CLASS, ARG1, ARG2, COUNT> ALIAS; \
template<> CLASS * ALIAS::instance = nullptr; \
template<> RET(CLASS::*ALIAS::fn)(ARG1, ARG2) = nullptr;
So that I could call it like so:
MEMBIND(void, Foo, float, float, 0, MemBindZero)
MEMBIND(void, OtherFoo, float, float, 1, MemBindOne)
I am curious about how to call function pointer in a map structure. Here is the details:
#include<iostream>
#include<map>
#include<vector>
#include<string.h>
using namespace std;
class FuncP;
typedef int(FuncP::*func) (int, int);
class FuncP
{
public:
map<int, func> fmap;
map<int, string> fstring;
public:
FuncP(){}
void initial();
int max(int x, int y);
int min(int x, int y);
int call(int op, int x, int y)
{
return (this->*fmap[op])(x, y);
}
};
void FuncP::initial()
{
fmap[0] = &FuncP::max;
fmap[1] = &FuncP::min;
fstring[0] = "fdsfaf";
}
int FuncP::min(int x, int y)
{
return (x<y)?x:y;
}
int FuncP::max(int x, int y)
{
return (x<y)?y:x;
}
int main()
{
func h = &FuncP::max;
FuncP *handle = new FuncP();
handle->initial();
cout<< handle->call(0, 1, 4); //1
cout<< (handle->FuncP::*fmap)[0](1,5); //2
return 0;
}
For the number 2 (handle->FuncP::*fmap)0; The compiler gives a error:
‘fmap’ was not declared in this scope
I am not sure why it happened. What the difference of the number 1 and 2 call methods?
As commented by Piotr, a correct way would be
(handle->*(handle->fmap[0]))(1, 5);
Explanation:
handle->fmap[0] gives you the function pointer. To call it, you need to dereference it, giving *(handle->fmap[0]) (parentheses optional)
and call it on the respecting object (handle), leaving us with the expression above.
This is essentially the same as your above statement (this->*fmap[op])(x, y) except of handle->fmap[0]instead offmap[op].
first of all I know that this is not possible in C++. But I hope someone can tell be a workaround for my problem. I have a class which represents a mathematical function:
class myClass:
{
private:
public:
myClass() {};
double value(double, double){ /* doing some complicated calculation here */} };
double integrate { /*calc*/ return integral; };
}
In integrate() I want to create a struct with a reference to value(). The struct is defined as follows:
struct gsl_monte_function_struct {
double (*f)(double * x_array, size_t dim, void * params);
size_t dim;
void * params;
};
(I need this struct to call the Monte-Carlo integration routines from GSL)
As said before I know that this is forbidden in C++. But is there any possibility to use gsl_monte_function_struct with a member function of myClass? If it is not possible that myClass can integrate itself, is it possible to call gsl_monte_function_struct from outside the class with value() as reference? Thanks in advance!
If understand you corretly, you want a pointer to a member function of myClass. You can achieve this by declaring the member function pointer as:
double (myClass::*value)(double,double)
This function can later be called on an instance as:
(instance.*value)(x,y);
Alternatively you can use std::bind to create a function object which can be called as an ordinary function without having to keep track of the instance on which it is called after the call to std::bind:
auto& value = std::bind(myClass::value, instance);
// ....
value(x,y);
Ok so far I found two solutions:
1) (General solution) Using an abstract base class which has a static pointer to the current instance and a static function that calls a function of the derived class. The static function can be used with a function pointer.
Example:
struct gsl_monte{
double (*f)(double y);
};
class myBase {
private:
static myBase* instance;
public:
myBase(){};
static void setInstance(myBase* newOne);
virtual double value(double x) =0;
static double callValue(double x);//{return value(x);}
};
class myClass : public myBase {
public:
myClass(){};
double value(double x) { return x; };
};
myBase* myBase::instance = new myClass();
double myBase::callValue(double x){return instance->value(x);}
void myBase::setInstance(myBase* newOne){instance=newOne;};
double g(double xx) {return xx;};
int main(int argc, char** argv ){
double x[2]; x[0]=1.3; x[1]=1.3;
myClass* instance = new myClass();
myBase::setInstance(instance);
instance->value(3);
std::cout << "Test " << myBase::callValue(5) << std::endl;
gsl_monte T;
T.f=&myBase::callValue;
double (*f)(double y, void*) = &myBase::callValue;
}
2) (Solution specific to my problem) Fortunatly the desired function accepts a parameter pointer, which I can use to pass the current object:
#include <iostream>
#include <functional>
using namespace std::placeholders;
struct gsl_monte{
double (*f)(double y, void*);
};
class myClass {
public:
myClass(){};
double value(double x) { return x; };
};
double valueTT(double x, void* param) { return static_cast<myClass*>(param)->value(x); };
int main(int argc, char** argv ){
double x[2]; x[0]=1.3; x[1]=1.3;
myClass* instance = new myClass();
instance->value(3);
gsl_monte T;
T.f=&valueTT;
double (*f)(double y, void*) = &valueTT;
}
Abstract
I have a class that stores a optimization problem and runs a solver on that problem.
If the solver fails I want to consider a sub-problem and solve using the same solver (and class).
Introduction
An optimization problem is essencially a lot of (mathematical) functions. The problem functions are defined outside the class, but the sub-problem functions are defined inside the class, so they have different types (e.g. void (*) and void (MyClass::*).
At first I thought that I could cast the member function to the non-member pointer-to-function type, but I found out that I cannot. So I'm searching for some other way.
Example Code
An example code to simulate my issue:
#include <iostream>
using namespace std;
typedef void (*ftype) (int, double);
// Suppose foo is from another file. Can't change the definition
void foo (int n, double x) {
cout << "foo: " << n*x << endl;
}
class TheClass {
private:
double value;
ftype m_function;
void print (int n, double x) {
m_function(size*n, value*x);
}
public:
static int size;
TheClass () : value(1.2), m_function(0) { size++; }
void set_function (ftype p) { m_function = p; }
void call_function() {
if (m_function) m_function(size, value);
}
void call_ok_function() {
TheClass ok_class;
ok_class.set_function(foo);
ok_class.call_function();
}
void call_nasty_function() {
TheClass nasty_class;
// nasty_class.set_function(print);
// nasty_class.set_function(&TheClass::print);
nasty_class.call_function();
}
};
int TheClass::size = 0;
int main () {
TheClass one_class;
one_class.set_function(foo);
one_class.call_function();
one_class.call_ok_function();
one_class.call_nasty_function();
}
As the example suggests, the member function can't be static. Also, I can't redefine the original problem function to receive an object.
Thanks for any help.
Edit
I forgot to mention. I tried changing to std::function, but my original function has more than 10 arguments (It is a Fortran subroutine).
Solution
I made the change to std::function and std::bind as suggested, but did not went for the redesign of a function with more 10 arguments. I decided to create an intermediate function. The following code illustrates what I did, but with fewer variables. Thanks to all.
#include <iostream>
#include <boost/tr1/functional.hpp>
using namespace std;
class TheClass;
typedef tr1::function<void(int *, double *, double *, double *)> ftype;
// Suppose foo is from another file. Can't change the definition
void foo (int n, int m, double *A, double *x, double *b) {
// Performs matrix vector multiplication x = A*b, where
// A is m x n
}
void foo_wrapper (int DIM[], double *A, double *x, double *b) {
foo(DIM[0], DIM[1], A, x, b);
}
class TheClass {
private:
ftype m_function;
void my_function (int DIM[], double *A, double *x, double *b) {
// Change something before performing MV mult.
m_function(DIM, A, x, b);
}
public:
void set_function (ftype p) { m_function = p; }
void call_function() {
int DIM[2] = {2,2};
if (m_function) m_function(DIM, 0, 0, 0);
}
void call_nasty_function() {
TheClass nasty_class;
ftype f = tr1::bind(&TheClass::my_function, this, _1, _2, _3, _4);
nasty_class.set_function(f);
nasty_class.call_function();
}
};
int main () {
TheClass one_class;
one_class.set_function(foo_wrapper);
one_class.call_function();
one_class.call_nasty_function();
}
PS. Creating a std::function with more than 10 variables seemed possible (compiled, but I didn't test) with
#define BOOST_FUNCTION_NUM_ARGS 15
#include <boost/function/detail/maybe_include.hpp>
#undef BOOST_FUNCTION_NUM_ARGS
But creating a std::bind for more than 10 arguments does not seem as easy.
std::function, std::bind, and lambdas are what you are looking for. In short, function pointers are very bad things and should be burned in fire. In long, std::function can store any function object which can be called with the correct signature, and you can use std::bind or a lambda to generate a function object that calls your member function quickly and easily.
Edit: Then you will just have to roll your own std::function equivalent that supports more than 10 arguments.
I'm reading the book by Daoqi Yang "C++ and Object Oriented Numeric Computing for Scientists and Engineers". He has a similar example to what I am showing below, but the exceptions are the class "P" I define and the second to last line (which doesn't work). My question is: why does my compiler generate and error when I supply the function member f.integrand? What can I do to correct this? The errors being generated are C3867, C2440, and C2973.
Here is the code:
class P{
public:
double integrand(double x){
return (exp(-x*x));
}
};
template<double F(double)>
double trapezoidal(double a, double b, int n)
{
double h=(b-a)/n;
double sum=F(a)*0.5;
for(int i=1;i<n;i++)
{
sum+=F(a+i*h);
}
sum+=F(b)*0.5;
return (sum*h);
}
double integrand2(double x){
return (exp(-x*x));
}
int main(){
P f;
cout<< trapezoidal<integrand2>(0,1,100)<<endl; // this works
cout<< trapezoidal<f.integrand>(0,1,100)<<endl; // this doesn't work
}
Template arguments must be compile-time constant expressions or types, and member functions require special handling anyway. Instead of doing this, use boost::function<> as an argument, and boost::bind to create the functor, e.g.
double trapezoidal(double, double, boost::function<double(double)>);
// ...
P f;
trapezoidal(0, 1, 100, integrand2);
trapezoidal(0, 1, 100, boost::bind(&P::integrand, boost::ref(f)));
If you have 0x-capable compiler, you can use std::function and std::bind instead.
Cat Plus Plus is correct - boost::bind is a good way to do this easily. I've also included an alternate solution with the following snippet of code:
class P{
private:
double a;
public:
double integrand(double x){
return (a*exp(-x*x));
}
void setA(double y){
a = y;
}
void getA(){
cout<<a<<endl;
}
struct integrand_caller {
P* p;
integrand_caller(P& aP) : p(&aP) {};
double operator()(double x) const {
return p->integrand(x);
};
};
};
template <typename Evaluator, typename VectorType>
VectorType trapezoidal(Evaluator f, const VectorType& a, const VectorType& b, int n)
{
VectorType h=(b-a)/n;
VectorType sum=f(a)*0.5;
for(int i=1;i<n;i++)
{
sum+=f(a+i*h);
}
sum += f(b)*0.5;
return (sum*h);
}
double integrand2(double x){
return (exp(-x*x));
}
int main(){
P f[5];
for(int i=0;i<5;i++){
f[i].setA(5*i);
f[i].getA();
cout<< trapezoidal(P::integrand_caller(f[i]),(double)0, (double)1, 100) << endl;
cout<<trapezoidal(boost::bind(&P::integrand,f[i],_1), 0.0, 1.0, 100)<<"\n"<<endl;
}
}