c ++派生类型的自动工厂注册

像我之前的许多人一样,我正在尝试让我的派生类型自动注册到我的工厂.我通读了许多问题,并试图专注于我在那里没有找到的内容.

Like many before me, I'm trying so get my derived types to automatically register with my factory. I read through many question and tried to focus on what I didn't find there.

除了自动注册之外,其他一切都运行良好.

I've got everything running nicely except the automatic registration.

我的目标:

  1. 自动注册我的基类的任何派生类Base
  1. 只有我标记为可注册
  2. 的课程
  3. 不仅是Base的直接子类
    • 例如: Base -> Device -> Camera -> 网络摄像头
    • 这将使使用 CRTP 如这个问题困难
  1. only classes I mark as registrable
  2. not only direct sub-classes of Base
    • ex: Base -> Device -> Camera -> Webcam
    • this would make using the CRTP like described in this question dificult

  • 对我想要注册的课程进行最少的更改 - 假人证明
  • 更喜欢使用注册器类而不是宏
    • 就像在这个问题中一样,但我不确定这是否依赖于 CRTP
    • minimal changes to the classes I want registered - dummies proof
    • would prefer using a registrator class than macros
      • like in this question, but I'm not sure if this is dependent on CRTP
      • 我有什么:

        template <class T>
        class abstract_factory
        {
            public:
                template < typename Tsub > static void register_class();
                static T* create( const std::string& name );
            private:
                // allocator<T> is a helper class to create a pointer of correct type
                static std::map<std::string, boost::shared_ptr<allocator<T> > > s_map;
        };
        

        • 模板化抽象工厂,std::string 作为键类型
        • 抽象工厂拥有所有成员和方法静态
        • 使用typeid自动恢复类名(注册时不需要文本名称)
        • 调用注册:abstract_factory::register_class();
          • templated abstract factory, with std::string as key type
          • abstract factory has all members and methods static
          • class name is recovered automatically with typeid (no need for text name when registering)
          • registration by calling: abstract_factory<Base>::register_class<MyDerived>();
          • 我尝试过的(或想尝试但不知道如何正确操作):

            • registratorclass:在 Derived.cpp 中静态实例化的模板化类,应在其构造函数中调用 abstract_factory::register_class()
              • 永远不会被调用或实例化
              • 如果我在 main() 中创建一个 Derived 的实例,这有效 -> 虽然有点违背了目的
              • registrator<Derived> class: templateded class that is instantiated statically in Derived.cpp and should call abstract_factory::register_class<Derived>() in it's constructor
                • never gets called or instantiated
                • if I make an instance of Derived in main() this works -> kinda defeats the purpose though

                可以使用任何建议,无论大小,thanx.

                Could use any advice, large or small, thanx.

                推荐答案

                我用单例带成员注册,基本上:

                I use a singleton with a member for registration, basically:

                template< typename KeyType, typename ProductCreatorType >
                class Factory
                {
                    typedef boost::unordered_map< KeyType, ProductCreatorType > CreatorMap;
                    ...
                };
                

                使用 Loki 之后,我得到了一些类似的东西:

                Using Loki I then have something along these lines:

                 typedef Loki::SingletonHolder< Factory< StringHash, boost::function< boost::shared_ptr< SomeBase >( const SomeSource& ) > >, Loki::CreateStatic > SomeFactory;
                

                注册通常使用宏完成,例如:

                Registration is usually done using a macro such as:

                #define REGISTER_SOME_FACTORY( type ) static bool BOOST_PP_CAT( type, __regged ) = SomeFactory::Instance().RegisterCreator( BOOST_PP_STRINGIZE( type ), boost::bind( &boost::make_shared< type >, _1 ) );
                

                这种设置有很多优点:

                • 适用于例如 boost::shared_ptr<>.
                • 不需要为所有注册需求维护一个庞大的文件.
                • 对于创作者来说非常灵活,任何事情都非常顺利.
                • 宏涵盖了最常见的用例,同时为替代方案敞开了大门.

                调用 .cpp 文件中的宏就足以在静态初始化期间在启动时注册类型.当类型注册是静态库的一部分时,这很有效,在这种情况下,它不会包含在您的二进制文件中.将注册编译为我见过的库的一部分的唯一解决方案是拥有一个巨大的文件,该文件将注册明确作为某种初始化例程的一部分.相反,我现在所做的是在我的库中创建一个客户端文件夹,用户将其作为二进制构建的一部分包含在内.

                Invoking the macro in the .cpp file is then enough to get the type registered at start up during static initialization. This works dandy save for when the type registration is a part of a static library, in which case it won't be included in your binary. The only solutions which compiles the registration as a part of the library which I've seen work is to have one huge file that does the registration explicitly as a part of some sort of initialization routine. Instead what I do nowadays is to have a client folder with my lib which the user includes as a part of the binary build.

                从您的要求列表中,我相信除了使用注册器类之外,这可以满足所有要求.

                From your list of requirements I believe this satisfies everything save for using a registrator class.

  • 相关文章