gpt4 book ai didi

c++ - 使用宏自动注册对象创建函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:57:13 25 4
gpt4 key购买 nike

基本上,我想为在许多头文件中定义的一堆类自动向对象工厂注册对象创建者函数。

this post 的最佳答案,提供了一个解决方案——但它不符合我的限制。

我正在处理现有的代码库。对于我需要注册的类,在类声明之后已经有一个宏将类作为参数。如果我能够扩展现有的宏定义以进行注册,那么将节省大量时间,因为无需更改现有代码。

我能想到的最接近的解决方案是创建一个宏,该宏定义注册该对象的方法的模板特化,然后调用先前定义的模板特化方法——从而链接所有注册调用。然后,当我想注册所有类时,我只需调用最近定义的特化,它就会按照 #include 出现的相反顺序注册所有内容。

下面,我发布了一个简单的工作示例,展示了我目前的解决方案。

唯一需要注意的是,我无法自动跟踪最后注册的类型以在链中调用。所以我一直将#define LAST_CHAIN_LINK 重新定义为最新的专用类型名。这意味着我必须在每个现有的宏调用之后添加两行#undef/#define——我真的很想避免这种情况。

主要问题:在下面的代码中,是否有任何方法可以定义 REGISTER_CHAIN 宏,使其在不使用 LAST_CHAIN_LINK #undef/#define 代码的情况下工作?

如果可以在 REGISTER_CHAIN 方法中重新定义 LAST_CHAIN_LINK 标记就好了...

我的猜测是使用 __COUNTER__ 预处理器功能可以实现一些解决方案,但在其中一个目标平台(使用 gcc 4.2.x 的 OS X)上不可用,因此不是一个选项。

简化示例(在 GNU C++ 4.4.3 上编译):

#include <map>
#include <string>
#include <iostream>

struct Object{ virtual ~Object() {} }; // base type for all objects

// provide a simple create function to derived classes
template<class T> struct ObjectT : public Object {
static Object* create() { return new T(); }
};

struct ObjectFactory {
// pass in creator function pointer to register it to id
static Object* create(const std::string& id, Object* (*creator)() = 0) {
static std::map<std::string, Object* (*)()> creators;
return creator && (creators[id] = creator) ? 0 : creators.find(id) != creators.end() ? (*creators.find(id)->second)() : 0;
}
template<class T = int> struct Register { static void chain() {} };
};


#define LAST_CHAIN_LINK // empty to start

#define REGISTER_CHAIN(T) \
template<> void ObjectFactory::Register<T>::chain() \
{ \
ObjectFactory::create(#T, T::create); \
std::cout << "Register<" << #T << ">::chain()\n"; \
ObjectFactory::Register<LAST_CHAIN_LINK>::chain(); \
}

struct DerivedA : public ObjectT<DerivedA> { DerivedA() { std::cout << "DerivedA constructor\n"; } };
REGISTER_CHAIN(DerivedA);
// Can these next two lines be eliminated or folded into REGISTER_CHAIN?
#undef LAST_CHAIN_LINK
#define LAST_CHAIN_LINK DerivedA

struct DerivedB : public ObjectT<DerivedB> { DerivedB() { std::cout << "DerivedB constructor\n"; } };
REGISTER_CHAIN(DerivedB);
// Can these next two lines be eliminated or folded into REGISTER_CHAIN?
#undef LAST_CHAIN_LINK
#define LAST_CHAIN_LINK DerivedB

struct DerivedC : public ObjectT<DerivedC> { DerivedC() { std::cout << "DerivedC constructor\n"; } };
REGISTER_CHAIN(DerivedC);
// Can these next two lines be eliminated or folded into REGISTER_CHAIN?
#undef LAST_CHAIN_LINK
#define LAST_CHAIN_LINK DerivedC

struct DerivedD : public ObjectT<DerivedD> { DerivedD() { std::cout << "DerivedD constructor\n"; } };
REGISTER_CHAIN(DerivedD);
// Can these next two lines be eliminated or folded into REGISTER_CHAIN?
#undef LAST_CHAIN_LINK
#define LAST_CHAIN_LINK DerivedD

int main(void)
{
// Call last link in the register chain to register all object creators
ObjectFactory::Register<LAST_CHAIN_LINK>::chain();
delete ObjectFactory::create("DerivedA");
delete ObjectFactory::create("DerivedB");
delete ObjectFactory::create("DerivedC");
delete ObjectFactory::create("DerivedD");
return 0;
}

示例输出:

> g++ example.cpp && ./a.out
Register<DerivedD>::chain()
Register<DerivedC>::chain()
Register<DerivedB>::chain()
Register<DerivedA>::chain()
DerivedA constructor
DerivedB constructor
DerivedC constructor
DerivedD constructor

最佳答案

我发现您的概念非常复杂,我不确定是否需要。从我的角度来看,添加以下代码可以避免您的问题:

#include <iostream>
#include <map>
#include <string>

struct Object{}; // Value Object


// provide a simple create function to derived classes
template<class T> struct ObjectT : public Object {

static Object* create() { return new T(); }
};

struct ObjectFactory {

std::map<std::string, Object* (*)()> creators_factory;

static ObjectFactory* instance()
{
static ObjectFactory* __self = NULL;
if (__self == NULL)
__self = new ObjectFactory();

return __self;

}

template <class T> bool reg(const std::string& id, Object* (*creator)() )
{
creators_factory[id] = creator;
return true;
}

// pass in creator function pointer to register it to id
static Object* create(const std::string& id) {
return instance()->creators_factory[id]();
}

};

#define REGISTER_CHAIN(T) bool isRegistered_##T = ObjectFactory::instance()->reg<T>(#T, T::create)

struct DerivedA : public ObjectT<DerivedA> { DerivedA() { std::cout << "DerivedA constructor\n"; } };
REGISTER_CHAIN(DerivedA);

struct DerivedB : public ObjectT<DerivedB> { DerivedB() { std::cout << "DerivedB constructor\n"; } };
REGISTER_CHAIN(DerivedB);


struct DerivedC : public ObjectT<DerivedC> { DerivedC() { std::cout << "DerivedC constructor\n"; } };
REGISTER_CHAIN(DerivedC);

struct DerivedD : public ObjectT<DerivedD> { DerivedD() { std::cout << "DerivedD constructor\n"; } };
REGISTER_CHAIN(DerivedD);

int main(void)
{
// Call last link in the register chain to register all object creators
//ObjectFactory::Register<LAST_CHAIN_LINK>::chain();
delete ObjectFactory::create("DerivedA");
delete ObjectFactory::create("DerivedB");
delete ObjectFactory::create("DerivedC");
delete ObjectFactory::create("DerivedD");
return 0;
}

希望对您有所帮助。

最好的问候,马丁

关于c++ - 使用宏自动注册对象创建函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6137706/

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