从字符串中减去类类型

时间:2016-02-26 18:29:33

标签: c++ string templates reflection introspection

This Answer中所述,只要知道基本类型,就可以从字符串中确定派生对象。我希望通过将BaseFactory作为模板来使代码更加灵活,从而产生以下可编译代码。

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


///Reflect and Register
#define MyType(BASE, TYPE) \
    static Registerer<BASE, TYPE> reg

#define Register(BASE, TYPE) \
    Registerer<BASE, TYPE> TYPE::reg(#TYPE)

template<class B>
class Factory
{
public:
    static B* from(const std::string& name)
    {
        return mapping[name];//should check if its a member
    }
    static void add(const std::string& name, B* instance)
    {
        mapping[name] = instance;
    }
    static std::map<std::string, B*> mapping;
};
template<class B>
std::map<std::string, B*> Factory<B>::mapping = std::map<std::string, B*>();


template<class B, class D>
class Registerer
{
public:
    Registerer(const std::string& name)
    {
        Factory<Base>::add(name, new D);//actually add
    }
};
///Deduce and Register


///Class examples implementing Registration
class Base
{
public:
    Base()
    {
        name = "Base Class";
    }
    const std::string& getName()
    {
        return name;
    }
protected:
    std::string name;
};
class Derived1 : public Base
{
public:
    Derived1()
    {
        name = "I am type 1.\n";
    }
    MyType(Base, Derived1);
};
Register(Base, Derived1);
class Derived2 : public Base
{
public:
    Derived2()
    {
        name = "I am type 2.\n";
    }
    MyType(Base, Derived2);
};
Register(Base, Derived2);
///Class examples implementing Registration


int main()
{
    std::string typeString1 = "Derived1";
    std::string typeString2 = "Derived2";

    std::cout << Factory<Base>::from(typeString1)->getName();
    std::cout << Factory<Base>::from(typeString2)->getName();

    return 0;
}

但是,这个代码崩溃了,显然是因为当Registerer调用add时,Factory :: mapping没有及时实例化。如This Answer中所述,有一个解决方案,即添加行

template class Factory<Base>;

这不能解决Visual Studio中的问题,这是我正在使用的。另一种可能性是明确地创建一个新类,但重点是首先使用模板。所以我想出了这个:

template<class B>
class Factory
{
public:
    static B* from(const std::string& name, B* instance = NULL)
    {
        static std::map<std::string, B*> mapping;
        if(instance != NULL)
        {
            mapping[name] = instance;
            return NULL;
        }
        else//should check if name is in map first
            return mapping[name];
    }
};

这是有效的,因为映射变量是在第一次调用函数时初始化的。不幸的部分是if check。

我试图找到解决方案:

  1. 不使用Factory中的单个函数来模拟两个函数。

  2. 使用单行而不是两行注册类的方法。

  3. 强制Base的子类自我注册,以防止用户意外注册它。

0 个答案:

没有答案