C ++ template for a pointer to a member function of an undefined class with different arguments, called an argument

I am not an advanced programmer. Short version of the problem: how can I create a template for a global function that calls a pointer to a member function of a class that is known only at runtime (and who has different arguments)?

The function is global, and its declaration is as follows:

template<class T> const double gExtFunc(const double &x, \ const double &y, \ const double &ep, \ const double &es, \ // function pointer here const double &a, \ const double &k, \ double &mid_OUT, \ short &i_OUT, \ double &eps_OUT, \ short &trip_OUT); 

This is called inside some ( virtual public ) classes. For example (not using ellipsis ):

 class DerivedA: virtual public Base { public: void funcA(...) { // ... m_varA = gExtFunc(...); // ... } // ... const double commonFunc(const double &a, const double &k) const; }; const double DerivedA::commonFunc(const double &a, const double &k) const { // ... } 

The Base class is for ordinary variables only. A pointer to a function points to commonFunc() , which has the same name in all virtual classes, but different definitions and types of arguments in each. For example, the above DerivedA uses it with two const double& arguments, whereas a DerivedE with:

 const double DerivedE::commonFunc(const int &n, const double &k) const; 

Now I managed to get it to work with the lambda function (based on this when I had only one m_varA ), which meant the argument of the function pointer from gExtFunc() :

 const double gExtFunc(..., std::function<const double(const double&, const double&)> fPnt, ...) 

and he was called, for example. inside DerivedA , as:

 m_varA = gExtFunc(..., [this](const double &a, const double &k){ return commonFunc(a, k); }, ...) 

and he worked, but only as long as he was called only within one class. As soon as I tried to call it DerivedE , it also failed for m_varE : was not declared in this scope , pointing to its definition of m_varE .

I saw this answer, but for this I need to first create an object that I cannot do. So I tried to get around this and replace the pointer to the function argument as follows:

 template<class T> // first the template, above the function const double gExtFunc(..., T *t, const double(T::*t)(const double&, const double&) fPnt, ...) 

and inside the definition: t->fPnt(...) . But what could you call gExtFunc() ? I tried this:

 m_varA = gExtFunc(..., new DerivedA(), &DerivedA::commonFunc, ...) 

but it fails, was not declared in this scope , as above. I'm stuck here. If there is an alternative to what I'm trying to do, I really want to change it.


EDIT:

As a temporary, ugly solution, I copied gExtFunc() each class that needs it, truncated and adjusted, including refusing a function pointer, only a direct call to the member function commonFunc() . At the moment there are only 3 cases, but the future can bring more, so I find it ugly and why the issue is still valid.

+5
source share
2 answers

This solution will do this (AClass is a test class):

 class AClass { private: std::string s_; unsigned short a_; public: AClass(const std::string& __s, unsigned short __a) : s_(__s), a_(__a) {} void m_Test(unsigned short __a, const std::string& __s) { a_ += __a; s_.append(__s); } unsigned short getA() { return a_; } std::string getS() { return s_; } }; template <typename T, typename R, typename ...Args> R proxycall(T & obj, R (T::*mf)(Args...), Args &&... args) { return (obj.*mf)(std::forward<Args>(args)...); } template <typename T, T> struct proxy; template <typename T, typename R, typename ...Args, R(T::*mf)(Args...)> struct proxy<R(T::*)(Args...), mf> { static R call(T & obj, Args &&... args) { return (obj.*mf)(std::forward<Args>(args)...); } }; int main() { AClass a("I ", 2); proxy<void(AClass::*)(unsigned short, const std::string&), &AClass::m_Test>::call(a, 23 , "am: "); std::cout << a.getS() << a.getA() << "\n"; std::cin.get(); return 0; } 

I do not remember who wrote this, but this is someone from the forum. Thanks to him.

Edit

You can also use polymorphism mechanisms if you can make your virtual virtual. I don't know if this fits your needs, but here is an example:

 class AClass; double gExtFunc(AClass* __acl, const double& __a, const double& __b, const double& __f); class AClass { private: const std::string& aClass = "AClass"; protected: double r_; public: AClass() : r_(0) {} void func_A() { r_ = gExtFunc(this, 2.0, 1.5, 300.011); } virtual double m_Test(const double& __a, const double& __b) { return __a * __b; } double getR() { return r_; } void setR(const double& __r) { r_ = __r; } virtual const std::string& getClass() { return aClass; } }; class BClass : virtual public AClass { private: const std::string& bClass = "BClass"; public: BClass() : AClass() {} void func_A() { r_ = gExtFunc(this, 3.0, 1.5, 311.128); } virtual double m_Test(const double& __a, const double& __b) { return __a * __b; } const std::string& getClass() { return bClass; } }; double gExtFunc(AClass* __acl, const double& __a, const double& __b, const double& __f) { double d = __acl->m_Test(__a, __b); return d * __f; } int main() { AClass a; BClass b; a.func_A(); b.func_A(); std::cout << a.getR() << "\n" << a.getClass() << "\n\n"; std::cout << b.getR() << "\n" << b.getClass() << "\n"; std::cin.get(); return 0; } 
+1
source

Feel free to lower my answer if this is wrong. I'm just trying to help. I don’t have the mental ability to read all this and understand your exact question, but I think I understand the basics of your problem. I assume that you are doing something like creating a function, where the argument can change as follows:

 template <typename T> func(T arg1){} 

and somewhere else in the code you expect T be int or char * or something else, but you are having trouble converting T to the appropriate type.

What I would do is work in memory. My function will be like

 enum types { OBJECT, INT, STRING }; int type; int addrOfType; void func(int addr, int typ) { type = typ; addrOfType = typ; } 

and cause him to do something like

 object argument; func((int)&argument,OBJECT); 

and somewhere else in the code you are retrieving data

 switch (type) { case OBJECT: object obj = *(object*)addrOfType; //do whatever with obj break; } 

I hope this helps. It looked like a tough question, so I decided that I would try to help when I was bored. Feel free to deny my answer if this is terrible. It is so hard to publish on mobile devices.

0
source

All Articles