我想知道如何使用变量参数映射函数,返回int类型并用字符串调用它。
仅举例......
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);
我只需要一个名为
的常用函数int CallFunction("funcname", param1, param2, ...);
例如
CallFunction("func1", 10, 20); /* calling function func1 and return func1 result*/
我知道如何使用具有常量参数的函数指针来映射函数,但是变量参数似乎很复杂..任何人都可以知道如何做到这一点。
我甚至探索了Variadic模板..但似乎使用字符串来复杂调用函数..
答案 0 :(得分:1)
我不确定这是否是您正在寻找的,但无论如何......
boost.any没有将其纳入标准,并且,如果您不知道它是什么,它允许您将任何C ++值存储在单个类型(any
)和如果您知道类型,请将其取回。以下是它的玩具实现:
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
包含两个指向函数的指针,这些函数知道如何复制以及如何销毁特定的C ++类型。 Value
可以包含任何类型,因为它由void *
和指向TypeHandler
的指针组成。当在实例上需要复制或销毁时,它会询问特定类型处理函数...
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;
}
};
请注意Value
是可复制的,可以按值传递,并且可以由函数返回。
任何可复制对象都可以隐式转换为Value
,我也可以使用to<T>()
将其转换回原始类型。
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);
}
这里我为1和2个参数创建了显式映射。可能这可以使用C ++ 11可变参数模板完成,我没试过。在C ++ 03库中,通常会看到这种类型的东西被复制粘贴到n = 20以覆盖合理的情况。
为了简化函数的注册,我编写了两个丑陋的宏。也许这可以使用可变参数宏或模板来完成(我不太确定它,特别是在地图中自动注册包装器)。
#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
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;
}
答案 1 :(得分:0)
我有完全相同的问题。
使用以下解决方案解决了该问题:
#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;
}
此代码段基于此answer。我只使用其他类/函数名称。