我正在为我们的API编写一个小包装器,但我遇到了一个问题。 来自外部客户端(JavaScript引擎)的每个调用都是来自ApiBase的名为execute的调用函数,所有参数都作为std :: string传递,没有在api调用中传递的内容,每个值都转换为字符串。
我的想法是使用指向成员函数的指针,并尝试将那些传递的字符串转换为编写特定函数的程序员需要的C ++类型。
例如:
struct MyApiForVeryImportantDevice{
void Init(int, int);
};
MyApiForVeryImportantDevice api_entry;
ApiBase* api = make_api(&api_entry, &MyApiForVeryImportantDevice::Init);
//serve api
代码api->execute("1", "2", "", "")
中的Somwhere被4个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);
}
答案 0 :(得分:1)
我认为 类型列表 可以在这里用来模拟可变参数模板。
类型列表是一种模板元编程构造,充当类型的已知列表。由Andrei Alexandrescu在他的书"Modern C++ design"中介绍 基本上,类型列表是这样的类:
template<typename HEAD , typename TAIL>
struct type_list
{
typedef HEAD head;
typedef TAIL tail;
};
可以用作下面的内容:
//A typelist wich stores int, bool, and char:
typedef type_list<int,type_list<bool,type_list<char, nil>>> list;
nil
是一种用作标记列表末尾的标记的类型。
我们可以使用C宏来定义快捷方式,使类型列表定义变得容易:
#define MAKE_TYPELIST_1( type_1 ) type_list<type_1,nil>
#define MAKE_TYPELIST_2( type_1 , type_2 ) type_list<type_1,MAKE_TYPELIST_1( type_2 )>
#define MAKE_TYPELIST_3( type_1 , type_2 , type_3 ) type_list<type_1,MAKE_TYPELIST_2( type_2 , type_3 )>
......等等。
您可以使用此构造来传递参数类型,而不使用可变参数模板:
template<typename T , typename R , typename ARGS_LIST>
class APICall ...
typedef APICall<...,MAKE_TYPELIST_3(std::string,std::string,std::string)> tree_strings_call;
我建议您查看Modern C ++设计的第三章。有关于类型列表,其操作(index_of,type_at等)的完整说明,以及它的使用的良好示例。