I would like to have some fair idea how to map functions with variable arguments,return type of int and call it by a string..
Just for an example...
int func1(int a, int b);
int func2(int a1, int b1 , int* c1);
int func3(char* dummy);
int func4(double x, long y, int z, char** table);
int func5(double d1, double b1);
int func6(int* p, double* q, int i);
I just need a common function called
int CallFunction("funcname", param1, param2, ...);
for example
CallFunction("func1", 10, 20); /* calling function func1 and return func1 result*/
I know how to map functions using functions pointers having constant arguments but variable arguments seems to be complicated.. could anyone shower some idea how to do it.
I even explored Variadic templates.. But seems to complicated calling functions using strings..
I had exact the same problem.
Solved it with this solution:
#include <iostream>
#include <map>
#include <string>
int func0(int x)
{
std::cout << x << std::endl;
}
int func1(int x, int y)
{
std::cout << (x + y) << std::endl;
}
template <class... Args>
struct MapHolder{
static std::map<std::string, int (*)(Args...)> CallbackMap;
};
template <class... Args>
std::map<std::string, int (*)(Args...)> MapHolder<Args...>::CallbackMap;
class Callback {
public:
template <class ...Args>
void RegisterFunction(std::string name, int (*func)(Args...)) {
MapHolder<Args...>::CallbackMap[name] = func;
}
template <class ...Args>
int ExecuteFunction(std::string name, Args &&... args) {
return MapHolder<Args...>::CallbackMap[name](std::forward<Args>(args)...);
};
};
int main(int argc, char *argv[])
{
Callback cb;
cb.RegisterFunction("func0", &func0);
cb.RegisterFunction("func1", &func1);
cb.ExecuteFunction("func0", 42);
cb.ExecuteFunction("func1", 42, 42);
return 0;
}
This snippet is based on this answer. I only use other class/function names.
I'm not sure if this is what you're looking for, but anyway...
1. Creating a generic value holder
boost.any didn't make it into the standard, and, in case you don't know what it is, it allows you to store any C++ value in a single type (any) and get it back if you know the type. The following is a toy implementation of it:
struct TypeHandler {
void* (*copyFrom)(void *src);
void (*destroy)(void *p);
};
template<typename T>
TypeHandler *thandler() {
struct THandler {
static void *copyFrom(void *p) { return new T(*(T *)p); }
static void destroy(void *p) { delete (T *)p; }
};
static TypeHandler th = { &THandler::copyFrom, &THandler::destroy };
return &th;
}
TypeHandler contains two pointer to functions that know how to copy and how to destroy a specific C++ type. A Value can hold any type because it's composed of a void * and a pointer to a TypeHandler. When copying or destroying is required on the instance it asks to the specific type handler function...
struct Value {
TypeHandler *th;
void *p;
Value(const Value& other) : th(other.th), p(th->copyFrom(other.p)) { }
template<typename T> Value(const T& x) : th(thandler<T>()), p(new T(x)) { }
~Value() { th->destroy(p); }
Value& operator=(const Value& other) {
if (this != &other) {
th->destroy(p);
th = other.th;
p = th->copyFrom(other.p);
}
return *this;
}
template<typename T>
Value& operator=(const T& other) {
th->destroy(p);
th = thandler<T>();
p = new T(other);
return *this;
}
template<typename T>
T& to() const {
if (th != thandler<T>()) throw Error("type mismatch");
return *(T*)p;
}
};
Note that Value is copyable and can be passed by value and can be returned by functions.
Any copyable object is implicitly convertible into a Value and I can also convert it back to the original type with to<T>().
2. Creating the name->function maps
std::map<std::string, Value (*)(const Value&)> map1;
std::map<std::string, Value (*)(const Value&, const Value&)> map2;
Value call(const std::string& name, const Value& x1) {
return map1.at(name)(x1);
}
Value call(const std::string& name, const Value& x1, const Value& x2) {
return map2.at(name)(x1, x2);
}
Here I've created explicit maps for 1 and 2 arguments. May be this can be done using C++11 variadic templates, I didn't try. In C++03 libraries it's common to see this kind of stuff copy-n-pasted up to say n=20 to cover reasonable cases.
3. Macrology
To simplify registration of functions I wrote two ugly macros. May be this can be done also using variadic macros or templates (I'm not so sure about it, especially the automatic registration of the wrapper in the map).
#define regfunc1(name, t1) \
Value name(const Value& x1) { \
return name(x1.to<t1>()); \
} \
struct name##_ { \
name##_() { map1[#name]=&name; } \
} name##_instance
#define regfunc2(name, t1, t2) \
Value name(const Value& x1, const Value& x2) { \
return name(x1.to<t1>(), x2.to<t2>()); \
} \
struct name##_ { \
name##_() { map2[#name]=&name; } \
} name##_instance
4. Use
double square(double x) {
return x*x;
}
double hyp2(double x, double y) {
return x*x+y*y;
}
int mylen(const std::string& s) {
return s.size();
}
regfunc1(square, double);
regfunc2(hyp2, double, double);
regfunc1(mylen, std::string);
int main() {
Value x = 42;
Value y = std::string("This is a test");
Value z = 3.14;
printf("%0.3f\n", call("square", z).to<double>());
printf("%0.3f\n", call("hyp2", z, z).to<double>());
printf("mylen(\"%s\") = %i\n",
y.to<std::string>().c_str(),
call("mylen", y).to<int>());
return 0;
}
Related
I am not an advanced programmer. The short version of the problem would be: how can I make a template for a global function that calls a pointer to a member function of classes that are only known at runtime (and who have different kind of arguments)?
The function is global and its declaration is this:
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 gets 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 just for common variables, mostly. The pointer to function points to commonFunc() which has the same name in all virtual classes, but different definitions and type of arguments in each. For example, the above DerivedA uses it with two const double& arguments, while a DerivedE with:
const double DerivedE::commonFunc(const int &n, const double &k) const;
Now, I managed to make it work with a lambda function (based on this, when I only had one m_varA), which meant the function pointer argument of gExtFunc() was this:
const double gExtFunc(..., std::function<const double(const double&, const double&)> fPnt, ...)
and it was called, for ex. inside DerivedA, as:
m_varA = gExtFunc(..., [this](const double &a, const double &k){ return commonFunc(a, k); }, ...)
and it worked, but only as long as it was called inside one class, only. As soon as I tried calling it in DerivedE, for m_varE, it, too, failed: was not declared in this scope, pointing to its definition of m_varE.
I have seen this answer, but that requires me to first create an object, which I can't do. So I tried to go around it and replace the pointer to function argument like this:
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 how would gExtFunc() be called? I tried this:
m_varA = gExtFunc(..., new DerivedA(), &DerivedA::commonFunc, ...)
but it fails, was not declared in this scope, same as above. I am stuck here. If there is an alternative to what I am trying to do, I'm very much willing to change it.
EDIT:
As a temporary, ugly solution, I copied the gExtFunc() to each class that needs it, trimmed & adjusted, including giving up pointer to function, just a direct call of the member function commonFunc(). There are only 3 cases, for now, but the future may bring more, which is why I consider this to be ugly and why the question is still valid.
This solution would do it (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 don't remember who wrote this, but it is someone from the forum. Thanks to him.
Edit
You could also use polymorphism mechanisms if you can make your commonFunc virtual. I don't know if this will suits your needs, but here is a sample:
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;
}
Feel free to downvote my answer if it is wrong. I am just trying to help.
I don't have the mental capacity to read all of that and understand your exact question, but I think I understand the basis of your problem. I am assuming you are doing something like making a function where an argument can vary like:
template <typename T> func(T arg1){}
and somewhere else in code you are expecting that T to be an int or a char * or whatever but you are having trouble converting T to the proper type.
What I would do is work in memory. My function would be something like
enum types {
OBJECT,
INT,
STRING
};
int type;
int addrOfType;
void func(int addr, int typ) {
type = typ;
addrOfType = typ;
}
and to call it do something like
object argument;
func((int)&argument,OBJECT);
and somewhere else in the code you are retrieving the data
switch (type) {
case OBJECT:
object obj = *(object*)addrOfType;
//do whatever with obj
break;
}
I hope that helped. It looked like a tough question so I figured I would attempt to try and help as I sit here bored. Feel free to neg my answer if it is terrible. It is so hard to post on mobile.
I have to use a function in library with variable parameters (createObject), the general usage is:
Class Point
{
public:
Point() {};
int x;
int y;
const char* name;
}
int main()
{
Point p;
createObject("%d",p.x,"%f",p.y,"%d",1,"%s",p.name);
}
Now i want to generalize usage of this function with Macro and Template, like this:
#define PARAM_Matrix(obj) "%d",obj.m,"%d",obj.n,"%d %d",obj[0][0],"%d %d",obj[0][1],"%d %d",obj[0][2]
#define PARAM_Person(obj) "%d",obj.age,"%s",obj.name
#define PARAM_Point(obj) "%d",obj.x,"%f",obj.y,"%d",1,"%s",obj.name
#define MAKE_PARAM(className,obj) PARAM_##className(obj)
class Person;
class Matrix;
class Point
{
public:
Point() {};
int x;
int y;
const char* name;
}
template<typename T> createGeneralize(T t)
{
return createObject(MAKE_PARAM(T,t));
}
int main()
{
Person per;
Matrix m;
Point p;
createGeneralize<Person>(per);
createGeneralize<Matrix>(m);
createGeneralize<Point>(p);
}
I expected that in createGeneralize() the C++ compiler expanding the macro to MAKE_PARAM(Point,t) (or MAKE_PARAM(Matrix,t)...). However, it is not the case, it always expands to MAKE_PARAM(T).
Your idea is not feasible because the preprocessor macros are converted to text before actual compiling. while the template arguments are substituted during compilation. so you get something like:
doMore (Point p)
{
T u, v; u = v;
}
i suggest just use templates.
Instead of macro, you may use template:
auto as_tuple(const Person& obj) { return std::make_tuple("%d", obj.age, "%s", obj.name); }
auto as_tuple(const Matrix& obj) { return std::make_tuple("%d", obj.m,"%d",obj.n,"%d %d",obj.obj[0][0],"%d %d",obj.obj[0][1],"%d %d",obj.obj[0][2]); }
auto as_tuple(const Point& obj) { return std::make_tuple("%d", obj.x,"%f",obj.y,"%d",1,"%s",obj.name); }
template<typename Tuple, std::size_t...Is>
void createGeneralize(const Tuple& t, std::index_sequence<Is...>)
{
return createObject(std::get<Is>(t)...);
}
template<typename T> void createGeneralize(const T& t)
{
const auto& tuple = as_tuple(t);
return createGeneralize(tuple, std::make_index_sequence<std::tuple_size<std::decay_t<decltype(tuple)>>::value>());
}
Live example
I need to do something like this:
template <typename Matrix_xx>
bool ProcessMatrix<Matrix_xx>::function1(Matrix_xx a) {
int x, y;
// ... some code here ... //
if (Matrix_xx == Matrix_1D) {
a->readFromFile(x);
} else if (Matrix_xx == Matrix_2D) {
a->readFromFile(x, y);
} // ...
}
i.e., to call different functions depends on the template argument. The code above wouldn't compile because there are only Matrix_1D::readFromFile(int x) and Matrix_2D::readFromFile(int x, int y). I don't want to split function1 into two different functions only because there would be a lot of doubled code. Is there another way?
Wrap the type-specific code in either overloaded function or explicitly specialized template:
void doReadFromFile(Matrix_1D &a, int x, int y)
{
a->readFromFile(x);
}
void doReadFromFile(Matrix_2D &a, int x, int y)
{
a->readFromFile(x, y);
}
template <typename Matrix_xx>
bool ProcessMatrix<Matrix_xx>::function1(Matrix_xx a) {
int x, y;
// ... some code here ... //
doReadFromFile(a, x, y);
}
If Matrix_xx is Matrix_1D, overloading will select the first overload, if it is Matrix_2D, overloading will select the second overload and if it's anything else, it won't compile. But if somebody provides new type of matrix, they can make it compile by defining the doReadFromFile for it.
This is generally useful trick and reason why standard library uses "traits"—they can be defined for class somebody gives you and they can be defined for non-class types. The "traits" can be either in the form of explicitly specialized templates or free functions, usually looked up with argument-dependent lookup (placed in the namespace of their argument, not the template).
For completeness, the explicit specialization would look like:
template <typename Matrix_xx>
struct doReadFromFile {};
template <>
struct<Matrix_1D> struct doReadFromFile {
void operator()(Matrix_1D &a, int x, int y) {
a->readFromFile(x);
}
}
template <>
struct<Matrix_1D> struct doReadFromFile {
void operator()(Matrix_1D &a, int x, int y) {
a->readFromFile(x, y);
}
}
Couldn't you make the argument to readFromFile a reference to a vector and let the Matrix_xx instance decide how many indices to fill in? That would eliminate the need for a conditional check.
You can get around that using the typeid operator.
Using it, your code would become:
template <typename Matrix_xx>
bool ProcessMatrix<Matrix_xx>::function1(Matrix_xx a) {
int x, y;
// ... some code here ... //
if (typeid(Matrix_xx) == typeid(Matrix_1D)) {
a->readFromFile(x);
} else if (typeid(Matrix_xx) == typeid(Matrix_2D)) {
a->readFromFile(x, y);
} // ...
}
or you could do it with a switch:
switch(typeid(Matrix_xx))
{
case typeid(Matrix_1D):
a->readFromFile(x);
break;
case typeid(Matrix_2D):
a->readFromFile(x,y);
break;
// etc, etc
}
[EDIT:] For those that say it won't compile, I'd be most interested in knowing what the functional difference between the code I left above and the code below, which is taken from a working project:
pdfArray.h
#ifndef PDFARRAY_H
#define PDFARRAY_H
#include "pdfObj.h"
#include "pdfTypes.h"
class pdfArray : public pdfObj
{
public:
pdfArray();
pdfArray(const pdfArray &src);
size_t size()
{
return(mArray->size());
}
void clear();
~pdfArray();
template <typename T> void addItem(const T *newItem)
{
//cout << typeid(T).name() << endl;
pdfObj *item = new T(*newItem);
mArray->push_back(item);
}
pdfObj *getItem(unsigned int itemIndex);
const bstring& toString();
pdfArray &operator=(const pdfArray &src);
private:
vecObjPtr *mArray;
};
#endif // PDFARRAY_H
excerpt from pdfArray.cpp
pdfArray::pdfArray(const pdfArray &src)
{
vecObjPtrIter iter;
pdfObj *ptr;
mArray = new vecObjPtr;
for (iter=src.mArray->begin(); iter!=src.mArray->end(); iter++)
{
ptr = *iter;
if (typeid(*ptr) == typeid(pdfString))
addItem( (pdfString*)ptr );
if (typeid(*ptr) == typeid(pdfInt))
addItem( (pdfInt*)ptr );
if (typeid(*ptr) == typeid(pdfFloat))
addItem( (pdfFloat*)ptr );
if (typeid(*ptr) == typeid(pdfArray))
addItem( (pdfArray*)ptr );
}
}
As an exercise for my personal enlightenment, I implement vector math with expression templates. I want to implement some operations that apply the same unary function to all elements to a vector expression. So far, I do this.
My base vector expression template is implemented like this
template <typename E>
class VectorExpr {
public:
int size() const { return static_cast<E const&>(*this).size(); }
float operator[](int i) const { return static_cast<E const&>(*this)[i]; }
operator E& () { return static_cast<E&>(*this); }
operator E const& () const { return static_cast<const E&>(*this); }
}; // class VectorExpr
Then, an object supposed to be a vector will look like this
class Vector2 : public VectorExpr<Vector2> {
public:
inline size_t size() const { return 2; }
template <typename E>
inline Vector2(VectorExpr<E> const& inExpr) {
E const& u = inExpr;
for(int i = 0; i < size(); ++i)
mTuple[i] = u[i];
}
private:
float mTuple[2];
};
Let's say I want to apply std::sin to all elements of an expression
template <typename E>
class VectorSin : public VectorExpr<VectorSin<E> > {
E const& mV;
public:
VectorSin(VectorExpr<E> const& inV) : mV(inV) {}
int size() const { return mV.size(); }
float operator [] (int i) const { return std::sin(mV[i]); }
};
Question => If I want to add more functions, I copy-paste what I do for the sin function, for every single function (like cos, sqrt, fabs, and so on). How I can avoid this kind of copy-pasting ? I tried things and figured out I'm still low in template-fu. No boost allowed ^^
template <typename F, typename E>
class VectorFunc : public VectorExpr<VectorFunc<F, E> > {
E const& mV;
public:
VectorSin(VectorExpr<E> const& inV) : mV(inV) {}
int size() const { return mV.size(); }
float operator [] (int i) const { return f(mV[i]); }
// this assumes the Functor f is default constructible, this is
// already not true for &std::sin. Adding the constructor that
// takes f, is left as an exercise ;)
F f;
};
In addition to the answer by pmr, The standard <cmath> functions aren't functors, so you couldn't use them directly to specify unique specialisations of your class - i.e. you wouldn't have a separate template instantiation for std::sin versus std::cos (which is what I gather you're aiming for? correct me if I've misunderstood you on that).
You could create a wrapper in order to map a function pointer to a distinct type, e.g.
#include <iostream>
template< void (*FuncPtr)() > struct Func2Type
{
void operator() () { FuncPtr(); }
};
void Hello() { std::cout << "Hello" << std::endl; }
void World() { std::cout << "world" << std::endl; }
int main()
{
Func2Type<Hello> test1;
Func2Type<World> test2;
test1();
test2();
}
That way you could use them as template arguments in the same way as a normal functor class
I have two methods f(vector<int>& x, ....) and g(DBConn& x, ....)
where the (....) parameters are all identical.
The code inside the two methods are completely identical except for one statement
where we do different actions based on the type of x:
in f(): we do x.push_back(i)
in g(): we do x.DeleteRow(i)
What is the simplest way to extract the common code into one method and yet
have the two different statements?
I am thinking of having a templated functor that overloads operator () (int a) but that seems overkill.
common_function(....)
{
}
f(vector<int>x,... )
{
x.push_back(i);
common_f(...);
}
g(DBConn& x, ....)
{
x.DeleteRow(i);
common_f(...);
}
You could write a simple adapter with two implementations, each calling the desired method of a different class.
class MyInterface {
public:
virtual doIt(int i) = 0;
}
class VectorImp : public MyInterface {
public:
vector<int>& v;
VectorImp(vector<int>& theVector) : v(theVector) {}
doIt(int i) { x.push_back(i); }
}
class DbImp : public MyInterface {
public:
DBConn& c;
VectorImp(DBConn& conn) : c(conn) {}
doIt(int i) { c.DeleteRow(i); }
}
template<class T>
struct Adapter;
template<>
struct Adapter<vector<int> >
{
static void execute(vector<int> &x, int i)
{
x.push_back(i);
}
};
template<>
struct Adapter<DBConn>
{
static void execute(DBConn &x, int i)
{
v.DeleteRow(i);
}
};
template<class T>
void f(T &t, ...)
{
...
Adapter<T>::execute(t, i);
...
}
OR:
template<class T>
struct adapter_traits;
template<>
struct adapter_traits<vector<int> >
{
typedef void (vector<int>::*PMF)(int);
static const PMF pmf = &vector<int>::push_back;
}
template<>
struct adapter_traits<DBConn>
{
typedef void (DBConn::*PMF)(int);
static const PMF pmf = &DBConn::DeleteRow;
}
template<class T>
void f(T &t, ...)
{
...
(t.*adapter_traits<T>::pmf)(i);
...
}
NOTE: I might have some syntax wrong but you get the idea.
Yet another idea:
template<class T>
void f(T &t, void (T::*p)(int), ...)
{
...
(t.*p)(i);
}
void g()
{
DBConn x;
vector<int> y;
f(x, &DBConn::DeleteRow, ...);
f(y, &vector<int>::push_back, ...);
}
Classic case for a functor:
#include <vector>
#include <DBConn.h>
// T: The type of the object that is to be manipulated.
// A: The type of the object that will do the manipulating
// This may be a functor object or a function pointer.
//
// As this is a template function the template parameters will
// be deduced by the compiler at compile time.
template<typename T,typename A>
void action(T& obj,A const& action/*,....*/)
{
// Do Stuff
action(obj,5);
// Do more Stuff
}
// Functor object
struct MyVectorAction
{
// Just defines the operator()
// Make sure it is a const method.
// This does the unique bit of code. The parameters should be what you pass into action
void operator()(std::vector<int>& data,int val) const {data.push_back(val);}
};
void f(std::vector<int>& x)
{
action(x,MyVectorAction()/*.... Params ....*/);
}
struct MyDBConnAction
{ void operator()(DBConn& data,int val) const {data.DeleteRow(val);} };
void g(DBConn& x)
{
action(x, MyDBConnAction());
}
int main()
{
std::vector<int> x;
f(x);
}
You could make a function that has the parameters of what you call (...), and this function can implement the logic that is the same in f() and g(). You could then change the implementation of f() and g() to call this new function instead of duplicating the logic. Be careful though if you're doing something duplicated before and after your unique lines. You may need two functions in that case. At any rate I think this would be preferable to having duplicated blocks of code.