在运行时解析枚举模板参数

时间:2014-05-14 01:31:22

标签: c++ templates

我正在尝试提出一个逻辑,它接受多个枚举并确定一个结构类型及其相应的大小以传递给第三方组件,我正在考虑使用特征来解决这个问题。方式:

蛮力解决方案(使用一个枚举)看起来像这样:

typedef enum FOO_TYPE
{
    FOO_TYPE_0 = 0,
    FOO_TYPE_1 = 1,
    ...
} FOO_TYPE;

switch (m_foo)
{
    case (FOO_TYPE_0):
    {
        FOO_0 Foo = {};
        UINT size = sizeof(Foo);
        m_thirdParty->CallFunction(&Foo, size);
    }
    break;

    case (FOO_TYPE_1):
    ...
}

我考虑使用traits来通过为每个FOO_TYPE定义特化来解决这个问题,但是在编译期间遇到了问题,因为我在运行时而不是在编译时选择了模板的特化。但是,对我来说,如果不产生switch语句的成本(当你考虑多个枚举类型时会很快增长),我怎么能解决这个问题并不是很明显。如果有人有想法,请告诉我。

template <FOO_TYPE FooType> 
struct FooTraits;

template <>
struct FooTraits<FOO_TYPE_0>
{
    typedef FOO_0 FooStruct;
};

{
    typedef FooTraits<m_foo> FooTraitsType; <== THIS USAGE CAUSES COMPILATION ERRORS
    FooTraitsType::FooStruct Foo = {};
    UINT size = sizeof(FooTraitsType::FooStruct);
    m_thirdParty->CallFunction(&Foo, size);
}

感谢。

1 个答案:

答案 0 :(得分:0)

您无法在运行时使用模板执行此操作,但您可以使用其他一些选项来本地化更改。

我的偏好是使用多态:

class Foo {
  static Foo* createFoo(FOO_TYPE type) {
  switch(type) {
     case FOO_TYPE_0:
       return new FooType0();
     case FOO_TYPE_1:
       return new FooType1();
  }
  virtual void callFunction(ThridParty thirdParty)=0;
}

class FooType0 : public Foo {
   void callFunction(ThridParty thirdParty) {
      FOO_0 Foo = {};
      UINT size = sizeof(Foo);
      m_thirdParty->CallFunction(&Foo, size);
   } 
}

class FooType1 : public Foo {
   void callFunction(ThridParty thirdParty) {
      FOO_1 Foo = {};
      UINT size = sizeof(Foo);
      m_thirdParty->CallFunction(&Foo, size);
   } 
}

您的交换机块将变为:

// Note this leaks ... see below for non-leaking version.
createFoo(m_foo)->callFunction(m_thirdParty);

现在每个FooTypeX类都有一些丑陋的重复,所以你可以通过模板化删除它:

class Foo {
  static Foo* createFoo(FOO_TYPE type) {
  switch(type) {
     case FOO_TYPE_0:
       return new FooX<FOO_1>();
     case FOO_TYPE_1:
       return new FooX<FOO_2>();
  }
  virtual void callFunction(ThridParty thirdParty)=0;
}

class FooX<BaseStruct> : public Foo {
   void callFunction(ThridParty thirdParty) {
      BaseStruct foo = {};
      UINT size = sizeof(foo);
      m_thirdParty->CallFunction(&foo, size);
   } 
} 

// A bit of a hack to prevent leaking. In real code you may want to 
// handle ownership differently.
std::unique_ptr<Foo>(createFoo(m_foo))->callFunction(m_thirdParty);