2013-08-21 125 views
1

我正在爲我們的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 

Somwhere代碼api->execute("1", "2", "", "")被調用4點10個字符串參數(總是4或10),無馬瑟多少參數,其中,在API調用傳遞(不要問我爲什麼...)。

我知道這可以用variadic模板完成,但不幸的是我不能在這個項目中使用它。 我的解決方案是基於「模擬variadic模板」,但它只是醜陋的。爲了支持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); 
} 
+1

你知道類型列表嗎?看到這裏:http://stackoverflow.com/questions/901907/how-to-use-typelists – LukeCodeBaker

回答

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; 

我建議你結帳現代C++設計的第三章。對類型列表,它的操作(index_of,type_at等)有一個完整的解釋,以及它使用的很好的例子。

+0

我想使用typelist來得到他的工作,但我如何存儲一個函數(指向成員funtcion )用任意數量的參數進一步調用? – sop3k