枚举值(int)到类型的动态映射 [英] Dynamic mapping of enum value (int) to type

查看:146
本文介绍了枚举值(int)到类型的动态映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看来,这个问题在我们的工作中很常见。

It appeared that this problem is quite common in our job.

我们通过网络发送int或枚举值,然后我们收到创建/调用特定的对象/函数。

We we are sending an int or enum value through the network, then we receive it we would like to create/call a particular object/function.

最简单的解决方案是使用switch语句,如下所示:

The most simply solution would be to use the switch statement, like below:

switch (value) {
    case FANCY_TYPE_VALUE: return new FancyType();
}

它的工作正常,但是我们会有大量的这些开关块,我们创造新的价值和类型,我们将需要更改所有这些。它似乎是正确的。

It works fine, but we would have plenty of these switch blocks, and when we create new value and type, we would need to change all of them. It does seem right.

其他可能是使用模板。但是我们不能,因为枚举的值在运行时定义。

Other possibility would be to use the templates. But we cannot, since the value of enum is defined in runtime.

是否有任何正确的设计模式,或任何正确的方法?

Is there any right design pattern for that, or any right approach?

这似乎是一个非常普遍和常见的问题,每天编码...

It seems like a very general and common problem in every day coding...

推荐答案

你实际上可以通过一些模板欺骗来做到这一点:

You can actually do this with some template trickery:

#include <map>

template <typename Enum, typename Base>
class EnumFactory {
  public:
    static Base* create(Enum e) {
      typename std::map<Enum,EnumFactory<Enum,Base>*>::const_iterator const it = lookup().find(e);
      if (it == lookup().end())
        return 0;
      return it->second->create();
    }
  protected:
    static std::map<Enum,EnumFactory<Enum,Base>*>& lookup() {
      static std::map<Enum,EnumFactory<Enum,Base>*> l;
      return l;
    }
  private:
    virtual Base* create() = 0;
};

template <typename Enum, typename Base, typename Der>
class EnumFactoryImpl : public EnumFactory<Enum,Base> {
  public:
    EnumFactoryImpl(Enum key)
      : position(this->lookup().insert(std::make_pair<Enum,EnumFactory<Enum,Base>*>(key,this)).first) {
    }
    ~EnumFactoryImpl() {
      this->lookup().erase(position);
    }
  private:
    virtual Base* create() {
      return new Der();
    }
    typename std::map<Enum,EnumFactory<Enum,Base>*>::iterator position;
};

这允许您从给定的枚举中创建一个新派生对象,通过说

This allows you to create a new derived object from a given enum, by saying

// will create a new `FancyType` object if `value` evaluates to `FANCY_TYPE_VALUE` at runtime
EnumFactory<MyEnum,MyBase>::create(value)

您必须拥有一些EnumFactoryImpl对象,这些对象在某些函数或命名空间中可能是静态的。

However, you have to have some EnumFactoryImpl objects, which could be static in some function or namespace.

namespace {
  EnumFactoryImpl<MyEnum,MyBase,Derived1> const fi1(ENUM_VALUE_1);
  EnumFactoryImpl<MyEnum,MyBase,Derived2> const fi2(ENUM_VALUE_2);
  EnumFactoryImpl<MyEnum,MyBase,Derived3> const fi3(ENUM_VALUE_3);
  EnumFactoryImpl<MyEnum,MyBase,FancyType> const fi1(FANCY_TYPE_VALUE); // your example
}

这些行是你的源代码映射的单一点code>枚举派生类型的值。所以你有一切在同一个位置,没有冗余(这消除了在添加新的派生类型时遗忘在某些地方更改它的问题)。

These lines are the single point where your source code maps enum values to derived types. So you have everything at the same location, and no redundancy (this eliminates the problem of forgetting to change it in some places, when adding new derived types).

这篇关于枚举值(int)到类型的动态映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆