c++ - 基于 CRTP 的类的工厂
问题描述
我将 CRTP 用于一组类:
#include <iostream>
#include <memory>
#include <string>
#include <typeinfo>
template<typename T, class Derived>
struct signal
{
T t; // Used elsewhere in the code...
static std::string name() {
return Derived::name_sub();
}
private:
signal() = default;
friend Derived;
};
struct signal_boolean : signal<bool, signal_boolean>
{
static std::string name_sub() {
return "boolean";
}
};
struct signal_integer : signal<int, signal_integer>
{
static std::string name_sub() {
return "integer";
}
};
int main() {
signal_boolean sb;
signal_integer si;
std::cout << sb.name() << std::endl;
std::cout << si.name() << std::endl;
return 0;
}
到目前为止一切都很好。现在我想signal
用一个序列化接口来扩展这个类。对于这个问题,序列化的样子并不重要。我们假设container
序列化程序为类的(反)序列化提供了一个:
// Serialization container
class container;
template<typename T, class Derived>
struct signal
{
static std::string name() {
return Derived::name_sub();
}
container to_container() const {
container c;
c.add_string("name", name());
return c;
}
private:
signal() = default;
friend Derived;
};
到目前为止一切都还好。我可以调用signal_boolean::to_container()
来序列化一个signal_boolean
对象。
但从这里开始,事情变得有点棘手:为了反序列化,我需要一个接受 acontainer
并返回适当派生signal
类的对象的工厂。
我遇到了这个宝石,它教会了我如何创建一个不错的可注册工厂。但是,我不知道如何正确地将其调整到我的代码中以处理我的signal
类。
我首先创建了signal_factory
实现可注册工厂模式的类:
static std::string demangle(const char* name) {
int status;
std::unique_ptr<char, void (*)(void *)> res{
abi::__cxa_demangle(name, NULL, NULL, &status), std::free};
return (status == 0) ? res.get() : name;
}
template <class base, class ...Args>
class factory
{
public:
template <class ...T>
static std::unique_ptr<base> make(const std::string &s, T&&... args) {
return data().at(s)(std::forward<T>(args)...);
}
template <class T>
struct registrar : base
{
friend T;
static bool registerT() {
const auto name = demangle(typeid(T).name());
factory::data()[name] = [](Args... args) -> std::unique_ptr<base> {
return std::make_unique<T>(std::forward<Args>(args)...);
};
return true;
}
static bool registered;
private:
registrar() : base(key{}) {
(void)registered;
}
};
friend base;
private:
class key
{
key() {};
template<class T>
friend struct registrar;
};
using func_type = std::unique_ptr<base> (*)(Args...);
factory() = default;
static auto& data() {
static std::unordered_map<std::string, func_type> s;
return s;
}
};
template <class base, class ...Args>
template <class T>
bool factory<base, Args...>::registrar<T>::registered = factory<base, Args...>::registrar<T>::registerT();
但现在我被困住了。我会让signal
类继承factory::registrar
自如上面链接的网站示例所示。但是,我的基类(在他们的示例中是Animal
类)是一个类模板。
我怎样才能使这项工作?我是否需要扩展factory::registrar
结构模板以接受模板模板参数?我试图这样做,但我很快迷失在模板语法中。
这甚至是正确的方法吗?我想要一种方法来根据我在运行时从反序列化获得的信息创建signal
派生类对象container
。
解决方案
推荐阅读
- sparql - 从 wikidata SPARQL 获取一个国家使用的语言列表
- css - Sass中特定条件下给P标签元素加边框
- typescript - Typescript 3.0.1 编译器选项 typeRoots 无法识别
- web-crawler - 使 StormCrawler 能够爬取具有多个 spout 的单个域
- opengl - ComputeShader 和 SSBO 读/写问题
- google-apps-script - 在 Google Spread 中使用 COLUMN 和 SCATTER 创建 COMBO 图表的脚本应用程序
- cassandra - 如果在 Cassandra 中使用 removenode 删除节点,如何找到副本成功流式传输
- javascript - Javascript 数据不在正确的单元格中
- php - 自定义 WordPress 循环
- php - Laravel + NGINX 给 403 禁止