2011-12-04 50 views
2

我試圖將this C++ code/answer(創建地圖string <-> some_array_of_predefined_function_types的類)轉換爲使用boost/preprocessor的更自動化的類。Boost預處理器多個模板類的生成

我已經創建了下面的代碼:

#include <boost/preprocessor.hpp> 
#include <iostream> 
#include <string> 
#include <map> 
#include <vector> 

#define CF_ADD_MAPS(z, n, T) \ 
std::map<std::string, identity< BOOST_PP_CAT(T, n) >::type* > \ 
BOOST_PP_CAT(T , BOOST_PP_CAT(n , _var)); 

#define CF_ADD_OPERATORS(z, n, T) \ 
operator identity< BOOST_PP_CAT(T, n) >::type*() \ 
{return \ 
BOOST_PP_CAT(p-> , BOOST_PP_CAT(T , BOOST_PP_CAT(n , BOOST_PP_CAT(_var, [n])))) ; \ 
} 

#define CF_ADD_INSERTERS(z, n, T) \ 
    void insert(std::string name, identity< BOOST_PP_CAT(T, n) >::type* ptr) \ 
{ \ 
    BOOST_PP_CAT(T , BOOST_PP_CAT(n , BOOST_PP_CAT(_var, [name]))) =ptr; \ 
} 

template <typename T> struct identity { typedef T type; }; 

#define CF_DEFINE_MAP_STRUCT_I(name, number)     \ 
template <BOOST_PP_ENUM_PARAMS(number, class T)>    \ 
class name {           \ 
     BOOST_PP_REPEAT(number, CF_ADD_MAPS, T)  \ 
     friend class apitemp;          \ 
     public: \ 
     class apitemp { \ 
     std::string n; \ 
     BOOST_PP_CAT(name, *) p; \ 
     public: \ 
      apitemp(std::string name_, BOOST_PP_CAT(name, *) parent) \ 
       : n(name_), p(parent) {} \ 
      BOOST_PP_REPEAT(number, CF_ADD_OPERATORS, T) \ 
     }; \ 
     BOOST_PP_REPEAT(number, CF_ADD_INSERTERS, T) \ 
     apitemp operator[](std::string n) {return apitemp(n, this);} \ 
}; 


#define CF_MAP_CLASS_NAME my_map 
#define CF_GENERATE_MAP_CLASS(z, n, data) CF_DEFINE_MAP_STRUCT_I(CF_MAP_CLASS_NAME, n) 
#define CF_MAX_MAP_TYPES_COUNT 2 
BOOST_PP_REPEAT(CF_MAX_MAP_TYPES_COUNT, CF_GENERATE_MAP_CLASS, x) 


/* 
class api { 
    //maps containing the different function pointers 
    std::map<std::string, identity<void()>::type* > voida; 
    std::map<std::string, identity<int(std::string, const int&)>::type* > stringcrint; 
    friend class apitemp; 
public: 
    //api temp class 
    //given an api and a name, it converts to a function pointer 
    //depending on parameters used 
    class apitemp { 
     std::string n; 
     api* p; 
    public: 
     apitemp(std::string name, api* parent) 
      : n(name), p(parent) {} 
     operator identity<void()>::type*() 
     {return p->voida[n];} 
     operator identity<int(std::string, const int&)>::type*() 
     {return p->stringcrint[n];} 
    }; 
    //insertion of new functions into appropriate maps 
    void insert(std::string name, identity<void()>::type* ptr) 
    {voida[name]=ptr;} 
    void insert(std::string name, identity<int(std::string, const int&)>::type* ptr) 
    {stringcrint[name]=ptr;} 
    //operator[] for the name gets halfway to the right function 
    apitemp operator[](std::string n) {return apitemp(n, this);} 
} myMap; 
*/ 

int hello_world(std::string name, const int & number) 
{ 
    name += "!"; 
    std::cout << "Hello, " << name << std::endl; 
    return number; 
} 

int main() { 
    my_map<int(std::string, const int &)> myMap; 
    myMap.insert("my_method_hello", &hello_world); 
    int a = myMap["my_method_hello"]("Tim", 25); 
    std::cout << a << std::endl; 
    std::cin.get(); 
} 

不與未來5個錯誤編譯:雖然預處理器生成

Error 1 error C2913: explicit specialization; 'my_map' is not a specialization of a class template 

Error 2 error C2133: 'myMap' : unknown size 

Error 3 error C2512: 'my_map' : no appropriate default constructor available 

Error 4 error C2039: 'insert' : is not a member of 'my_map' 

Error 5 error C2676: binary '[' : 'my_map' does not define this operator or a conversion to a type acceptable to the predefined operator 

template <> 
class my_map { 
    friend class apitemp; 
public: 
    class apitemp { 
     std::string n; 
     my_map* p; 
    public: apitemp(std::string name_, my_map* parent) : n(name_), p(parent) {} 
    }; 
    apitemp operator[](std::string n) { 
     return apitemp(n, this); 
    } 
}; 
template < class T0> 
class my_map { 
    std::map<std::string, identity<T0>::type* > T0_var; 
    friend class apitemp; 
public: 
    class apitemp { 
     std::string n; 
     my_map* p; 
    public: 
     apitemp(std::string name_, my_map* parent) : n(name_), p(parent) {} 
     operator identity<T0>::type*() { 
      return p->T0_var[0] ; 
     } 
    }; 
    void insert(std::string name, identity<T0>::type* ptr) { 
     T0_var[name] =ptr; 
    } 
    apitemp operator[](std::string n) { 
     return apitemp(n, this); 
    } 
}; 

我想知道什麼我做錯了,如何讓它編譯?

+1

您的專業化位於您的主模板之前,應該是相反的方式。順序很重要,首先是主要的,然後是專業化。 –

+1

請問,你可以在你的問題上寫下更多的努力,而不僅僅是轉儲一些代碼?我注意到現在有一​​段時間了,這是[你的(很多)問題](http://stackoverflow.com/users/1056328/mywalljson)的一種模式,坦率地說,它並沒有表現出很多的尊重。 SO是一個志願者社區,我認爲你可以小心謹慎,不要浪費人們的時間。謝謝。 – sehe

回答

1
template <> 
class my_map { 
    // ... 
}; 

問題在於BOOST_PP_ENUM_PARAMS,它也會生成一個0參數版本。由於0-參數版本(template<>)引入了專業化,所以它會出錯。修復:至少有一個固定的參數。

下一個問題:您不能根據模板參數「重載」類。他們必須有不同的名稱,或者以其他方式進行結構化,部分專業化或其他方式。

+0

'你不能根據模板參數「重載」類。' (那麼你怎麼得到這個?)(順便說一句,我們是如何在Boost.Overload中完成的,它有像'overload f;'...?) – myWallJSON

+0

@myWallJSON:這是基於部分專業化。'template struct overload; template struct overload '('''一般意義上的「重複」,在語言中不是這樣)。 – Xeo