2011-12-04 44 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