C++ 使用模板为特定枚举值创建方法

C++ using templates to create methods for specific enum values

我想编写一个方法,让编译器根据特定的枚举值生成多个方法。

下面我有一些 isValid*() 方法。如您所见,它们都具有相同的结构,因此我想将它们组合成一个方法。也许模板对此有用?也许不是。

类似于此伪代码(为清楚起见进行了编辑):

enum Dir { East, West, South, North }

bool isValidFromWest(const Dir dir)
{
  switch (dir)
  {
    case West:    return foo(dir);
    case East:    return true;
    case North:   return false;
    case South:   return false;
  }
}

bool isValidFromEast(const Dir dir)
{
  switch (dir)
  {
    case East:    return foo(dir);
    case West:    return true;
    case North:   return false;
    case South:   return false;
  }
}

bool isValidFromSouth(const Dir dir)
{
  switch (dir)
  {
    case South:   return foo(dir);
    case North:   return true;
    case West:    return false;
    case East:    return false;
  }
}

bool isValidFromNorth(const Dir dir)
{
  switch (dir)
  {
    case North:   return foo(dir);
    case South:   return true;
    case West:    return false;
    case East:    return false;
  }
}

是否有一种编译时方法可以将这些方法组合成一个既能保持性能又不会牺牲太多代码清晰度的方法。

模板选择发生在传递给模板的类型之上 function/user 定义的类型,而不依赖于枚举等值。

如果只是想切换Enum,不需要模板,代码如下:

#include<iostream> 
enum Dir { East, West };


void doStuff()
{
    std::cout<<"doStuff"<<std::endl;
}
// This method should be resolved at compile time
void  opposite()
{
   std::cout<<"Opposite"<<std::endl;
}



void  isValid(const Dir dir)
{
  switch (dir)
  {
    case East:
       doStuff();
    case West:
        opposite();

  }
}
int main()
{
    isValid(East);
    return 0;
}

模板在这种情况下很有用,下面的代码可能会满足您的要求。

为了简单起见,需要手动将enum Dir的值改为一些特殊值(两个相反方向之和为零)。

enum Dir{East = -2, West = 2, South = -1, North = 1};

bool foo(const Dir dir)
{
    //Do something
    return false;
}

template< Dir n >
struct CalDir
{
    static bool isValid(const Dir dir)
    {
        switch (dir)
        {
        case n:     return foo(dir);
        case 0 - n: return true;
        default:    return false;
        }
    }
};

int main()
{
    Dir a = East;
    CalDir<East>::isValid(a); //Equivalents to isValidFromWest(a)
    Dir b = North;
    CalDir<South>::isValid(b);//equivalents to isValidFromSouth(b)

    return 0;
}