注册一个C++类,以便函数稍后可以循环访问所有已注册的类
Register a C++ class so that later a function can iterate over all registered classes
我正在尝试编写一个在运行时动态加载其扩展的应用程序。我使用 Boost 预处理器库编写了一个预处理器函数,该函数给定一个名称列表,为每个名称声明一个类(并使所有这些名称都成为某个 AbstractPlugin 类的子类),然后声明包含该类的 Boost MPL 序列。然后我写了一个类,如果它可以转换为该MPL序列中的任何类型,则尝试指向AbstractPlugin的指针。这里的问题是我的预处理器函数需要我想要创建和加载的所有扩展的完整列表。是否有一些技术可以让我在单独的文件中注册每个扩展名?
更新:
我相信,我对情况的解释太模糊了,所以我决定更具体。
我想定义扩展类型的集合。对于每种扩展类型,可以有任意数量的扩展。在运行时,程序加载外部库,解析入口点函数,调用它,从而获得指针。然后,它尝试将该指针强制转换为所有已注册的扩展类型(使用 dynamic_cast
,因此扩展类型的类都继承自某个多态基类)。如果强制转换为某个扩展类型成功,则强制转换指针将用于调用该扩展类型的特殊处理程序。
类型的数量在编译时是已知的(而扩展的数量显然是无限的)。使用我的 aproach,loader 类使用此知识来检查每种扩展类型是否存在处理程序(如果没有,则程序不编译)。此外,我的 aproach 不会强制扩展类型的类知道有关加载器的任何信息(因此很容易修改加载器)。但是,如果每个扩展类型都自行注册,则会更方便。
您可以在某种集合中使所有类都自行注册。这是一个骨架方法:
Base.hpp:
#include <memory>
#include <unordered_map>
#include <string>
struct Base
{
virtual ~Base() = default;
using create_f = std::unique_ptr<Base>();
static void registrate(std::string const & name, create_f * fp)
{
registry()[name] = fp;
}
static std::unique_ptr<Base> instantiate(std::string const & name)
{
auto it = registry().find(name);
return it == registry().end() ? nullptr : (it->second)();
}
template <typename D>
struct Registrar
{
explicit Registrar(std::string const & name)
{
Base::registrate(name, &D::create);
}
// make non-copyable, etc.
};
private:
static std::unordered_map<std::string, create_f *> & registry();
};
基.cpp:
#include "Base.hpp"
std::unordered_map<std::string, Base::create_f *> & Base::registry()
{
static std::unordered_map<std::string, Base::create_f *> impl;
return impl;
}
现在要在客户端中使用它:
派生.hpp:
#include "Base.hpp"
struct Derived : Base
{
static std::unique_ptr<Base> create() { return std::make_unique<Derived>(); }
// ...
};
派生.cpp:
#include "Derived.hpp"
namespace
{
Base::Registrar<Derived> registrar("MyClass");
}
Base::Registrar<Derived>
的构造函数负责在名称 "MyClass"
下注册类Derived
。您可以通过以下方式动态创建Derived
实例:
std::unique_ptr<Base> p = Base::instantiate("MyClass");
代码可以/应该通过检测重复注册、打印可用类列表等来改进。 请注意我们如何避免任何静态初始化排序问题,我将实际的注册表映射对象设置为块静态对象,该对象保证在首次使用之前初始化,因此仅在最后一次使用后销毁。
使用抽象工厂模式实现这样的扩展框架并不难。
http://en.wikipedia.org/wiki/Abstract_factory_pattern
您可以在全局列表中注册这些抽象的工厂函数/对象,并基于它执行任何您想做的事情。
我想要的是不可能的。原因是在此上下文中"寄存器"意味着"将类型放入类型序列中",并且类型序列是不可变的,因为它们本身就是类型。因此,应该手动创建此类型序列,或者按照某些人的建议将"注册"移动到运行时。
- 如何循环打印顶点结构
- 如何在C++中从两个单独的for循环中添加两个数组
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 正在尝试了解输入验证循环
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- 循环后如何继续阅读
- Ardunio UNO解决了多个重叠的定时器循环
- Eigen如何在容器循环中干净地附加矩阵
- 在某些循环内使用vector.push_back时出现分段错误
- 无法将结构注册为增强几何体3D点
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 为什么我的for循环不能正确获取argv
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- while循环中while循环的时间复杂度是多少
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 为什么在这个代码结束循环中没有得到结束
- 在基于范围的for循环中使用结构化绑定声明
- 用于C++中带有数组和指针的循环
- 注册一个C++类,以便函数稍后可以循环访问所有已注册的类
- Glutkeyboard输入未注册没有奇数循环帮助