代码之家  ›  专栏  ›  技术社区  ›  den bardadym hakatashi

具有外部实现的C++静态模板

  •  0
  • den bardadym hakatashi  · 技术社区  · 16 年前

    我有一个简单的注册表模式:

    class Object
    {
    //some secondary simple methods
    };
    
    #define OBJECT_DEF(Name) \
     public: \
      static const char* Name() { return Name; } \
     private:
    
    
    class Registry
    {
     struct string_less {
      bool operator() (const std::string& str1, const std::string& str2) {
       for(int i = 0; i < str1.size() && i < str2.size(); ++i) {
        if(str1[i] != str2[i])
         return str1[i] < str2[i];
       }
       return str1.size() < str2.size();
      }
     };
    
     typedef boost::shared_ptr < Object> ptrInterface;
     typedef std::map < std::string,  ptrInterface, string_less > container;
     container registry;
    
     static Registry _instance;
    
     ptrInterface find(std::string name);
    
    protected:
     Registry () {}
     ~Registry () {}
    
    
    public:
    
    
     template < class T >
     static T* Get(); // I want to write so !!!
    
     template < class T >
     static bool Set(T* instance, bool reSet = false);
    };
    

    如果我有一个exteds对象的类:

    class Foo : public Object {
        OBJECT_DEF("foo");
    //smth
    };
    

    我想这样使用注册表:

    Registry::Set(new Foo());
    

    或

    Registry::Get<Foo>();
    

    如何通过外部实现模拟静态模板?

    1 回复  |  直到 16 年前
        1
  •  1
  •   Loki Astari    16 年前

    我不会对OBJECT_DEF()使用hack

    每个类都有一个唯一的名称(由编译器定义),可以通过type_info访问该名称

    然后我会使用boost any对象将这些信息很好地存储在地图中。

    我还没查过。
    但现在,register可以用于任何类型。

    #include <map>
    #include <boost/any.hpp>
    #include <typeinfo>
    #include <string>
    #include <iostream>
    
    class Register
    {
        static std::map<std::string, boost::any>       data;
    
        public:
            // If you just want to store pointers then:
            //     alter the input parameter to Set() to be T*
            //     alter the output of Get() to be T* and modify the any_cast.
            // 
            // If you are just storing pointers I would also modify the map
            // to be a boost::pointer_map so that ownership is transfered
            // and memory is cleaned up.
            template<typename T>
            static void Set(T const& value)
            {
                data[std::string(typeid(T).name())] = boost::any(value);
            }
    
            template<typename T>
            static T Get()
            {
                return boost::any_cast<T>(data[std::string(typeid(T).name())]);
            }
    
    
    };
    
    std::map<std::string, boost::any>       Register::data;
    
    int main()
    {
        // Currently this line will leak as register does not take ownership.
        Register::Set(new int(1));
    
        // This line works fine.
        Register::Set(int(5));
    
        std::cout << *(Register::Get<int*>()) << "\n";
        std::cout << Register::Get<int>() << "\n";
    }
    
    推荐文章