枚举值的模板专业化

Template specialization for enum values

本文关键字:专业化 枚举      更新时间:2023-10-16

是否可以为单个枚举值专业化类方法?具体来说,我有一个枚举和类,如下:

#include <iostream>
#include <stdio.h>
using namespace std;
enum class Animal { dog, cat, bird  };
class Sound
{
   public:
      static void getSound ( const Animal& arg )
      {
         switch ( arg )
         {
           case Animal::dog:
             // dog specific processing
             break;
           case Animal::cat:
             // cat specific processing
             break;
           case Animal::bird:
             // bird specific processing
             break;
           default:
             return;
         }
      }
};

我想为每个枚举值专门化getoind函数,以摆脱开关案例。这样的模板专业化吗?

是的,这是可能的。查看下面的样本。

#include <iostream>
#include <stdio.h>
using namespace std;
enum class Animal { dog, cat, bird  };
class Sound
{
   public:
      template<Animal animal>
      static void getSound ();
};
template<>
void Sound::getSound<Animal::dog> ()
{
    // dog specific processing
}
template<>
void Sound::getSound<Animal::cat> ()
{
    // cat specific processing
}
template<>
void Sound::getSound<Animal::bird> ()
{
    // bird specific processing
}
int main()
{
    Sound::getSound<Animal::dog>();
}

我不明白为什么要专业。如果此示例是指示性的,并且您的枚举器是顺序的,并且从0开始,则可以使用查找表:

enum class Animal { dog, cat, bird, count = (bird - dog + 1) };
static std::string getSound ( Animal arg ) // Pass an enumeration by value, it's cheaper
{
  std::array<char const *, static_cast<std::size_t>(Animal::count)> const sound {{
    "bark", "meow", "chirp"
  }};
  return sound.at(static_cast<std::size_t>(arg));
}

就是这样。它还用抛出的异常来代替"unknown"字符串。我觉得这是有必要的,因为登记枚举意味着我们希望严格检查所通过的价值。并打破是一种特殊情况。


即使是您编辑的问题也可以进行查找表:

static void getSound ( Animal arg ) // Pass an enumeration by value, it's cheaper
{
  std::array<std::function<void(void)>,
            static_cast<std::size_t>(Animal::count)> const handler{{
    [] { /*Process for dog*/ },
    [] { /*Process for cat*/ },
    [] { /*Process for bird*/ }
  }};
  handler.at(static_cast<std::size_t>(arg))(); // The last () is invocation
}