gpt4 book ai didi

c++ - CRTP 自动注册工厂(静态初始化顺序失败)

转载 作者:行者123 更新时间:2023-11-30 03:18:33 25 4
gpt4 key购买 nike

我正在尝试自动注册 CRTP 工厂类。我的目标是不使用宏注册类类型并且不显式调用注册方法。

我尝试基于 this answer :

工厂.h

template<typename Base>
struct Factory{
static Base* create(const QString& name){
auto callable = map.value(name);
return callable();
}

template<typename Derived>
static void subscribe(QString name){
// insert already-exist-check here
qDebug() << "registered: " << name;
map.insert(std::move(name), [](){return new Derived{};});
}

static QMap< QString, std::function<Base*(void)> > map;
};

template<typename Base>
QMap< QString, std::function<Base*(void)> > Factory<Base>::map;


template<typename Base, typename Derived>
class Registrable{
protected:
virtual QString registerName() const = 0;

Registrable(){
isRegistered;
}
~Registrable() = default;

static bool init(){
Derived t;
Factory<Base>::template subscribe<Derived>(t.registerName());
return true;
}

private:
static bool isRegistered;
};

template<typename Base, typename Derived>
bool Registrable<Base, Derived>::isRegistered = Registrable<Base, Derived>::init();

主要.cpp

struct MyFactoryBase{
virtual ~MyFactoryBase() = default;
virtual void method() const = 0;
};

struct MyFactory1 : public MyFactoryBase, public Registrable<MyFactoryBase, MyFactory1>{
QString registerName() const override{
return "Class1";
}
void method() const override{ qDebug() << "yay Class1"; }

MyFactory1() : MyFactoryBase(), Registrable<MyFactoryBase, MyFactory1>(){}
};

struct MyFactory2 : public MyFactoryBase, public Registrable<MyFactoryBase, MyFactory2>{
QString registerName() const override{
return "Class2";
}
void method() const override{ qDebug() << "yay Class2"; }

MyFactory2() : MyFactoryBase(), Registrable<MyFactoryBase, MyFactory2>(){}
};

int main(){
// auto* fac = Factory<MyFactoryBase>::create("Class1");
// auto* fac2 = Factory<MyFactoryBase>::create("Class2");
}

在第一次订阅期间尝试使用 map.insert() 时,它因段错误而崩溃。我缺少什么?

最佳答案

正如评论中所建议的那样,它是一个 static initialization order fiasco .

我按照 ISOCpp 中的建议解决了它 How do I prevent the “static initialization order problem” for my static data members?

In any event, it’s always portable and safe to change the X::x_ static data member into a static member function:

变化多端

static QMap< QString, std::function<Base*(void)> > map;

   static QMap< QString, std::function<Base*()> >& map(){
static QMap< QString, std::function<Base*()> > map;
return map;
}

并使用 map() 更新来自 map 的所有调用解决了这个问题。

int main(){
auto* fac = Factory<MyFactoryBase>::create("Class1");
auto* fac2 = Factory<MyFactoryBase>::create("Class2");

fac->method();
fac2->method();

return 0;
}

输出:

registered: Class1
registered: Class2
yay Class1
yay Class2

关于c++ - CRTP 自动注册工厂(静态初始化顺序失败),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54629894/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com