我正在为我们的 API 编写一个小包装器,但遇到了一个问题。来自外部客户端(JavaScript 引擎)的每次调用都是从名为 execute 的 ApiBase 调用函数,所有参数都以 std::string 的形式传递,与 api 调用中传递的无关,每个值都转换为字符串。
我的想法是使用指向成员函数的指针并尝试将那些传递的字符串转换为编写特定函数的程序员需要的 C++ 类型。
例如:
struct MyApiForVeryImportantDevice{
void Init(int, int);
};
MyApiForVeryImportantDevice api_entry;
ApiBase* api = make_api(&api_entry, &MyApiForVeryImportantDevice::Init);
//serve api
代码中的 Somwhereapi->execute("1", "2", "", "")
使用 4 o 10 个字符串参数(总是 4 或 10)调用,不知道在 api 调用中传递了多少参数(不要问我为什么......)。
我知道这可以用可变参数模板来完成,但不幸的是我不能在这个项目中使用它。我的解决方案基于“模拟可变参数模板”,但它很丑。为了支持 10 个参数,我需要编写 10 个类 ApiCall 和 10 个 make_api 函数,这很容易出错,您还有其他想法吗?某种 mpl(也许是类型列表?)?下面显示的代码只是 2 和 10 参数的示例,对于 0-10 参数,我需要类似的东西。
问候。
template<class T>
T convert(const string& v){
return T();
}
template<>
int convert(const string& v)
{
return boost::lexical_cast<int>(v);
}
template<class T, class R, class A0, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
class ApiCall : public ApiBase
{
typedef T result_type;
typedef R class_type;
typedef boost::function<result_type(class_type*,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9)> functor_type;
ApiCall(T* obj, functor_type f)
{
func = boost::bind(f, _1, obj);
}
virtual void execute(const string& param1, const string& param2, const string& param3, const string& param4)
{
func(convert<A0>(param0), convert<A1>(param1), convert<A2>(param2), convert<A3>(param3), convert<A4>(param4));
}
virtual void execute(const string& param0, const string& param1, const string& param2, const string& param3,
const string& param4, const string& param5, const string& param6, const string& param7
const string& param8, const string& param9)
{
func(convert<A0>(param0), convert<A1>(param1), convert<A2>(param2), convert<A3>(param3), convert<A4>(param4), convert<A5>(param5),
convert<A6>(param6),convert<A7>(param7), convert<A8>(param8), convert<A9>(param9));
}
private:
functor_type func;
};
template<class T, class R, class A0, class A1>
class ApiCall : public ApiBase
{
typedef R result_type;
typedef T class_type;
typedef boost::function<result_type(class_type*,A0, A1)> functor_type;
ApiCall(T* obj, functor_type f)
{
func = boost::bind(f, _1, obj);
}
virtual void execute(const string& param1, const string& param2, const string& param3, const string& param4)
{
func(convert<A0>(param0), convert<A1>(param1));
}
virtual void execute(const string& param0, const string& param1, const string& param2, const string& param3,
const string& param4, const string& param5, const string& param6, const string& param7
const string& param8, const string& param9)
{
func(convert<A0>(param0), convert<A1>(param1));
}
private:
functor_type func;
};
template<class T, class R, class A0, class A1>
ApiCall<T, R, A0, A1>* make_api(T obj, R(T::*fun)(A0, A1))
{
return new ApiCall<T,R,A0,A!>(obj, fun);
}
template<class T, class R, class A0, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
ApiCall<T,R,A0,A1,A2,A3,A4,A5,A6,A7,A8, A9>* make_api(T obj, R(T::*fun)(A0))
{
return new ApiCall<T,R,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9>(obj, fun);
}