【问题标题】:Template specialization for enum values枚举值的模板特化
【发布时间】:2017-12-06 04:42:40
【问题描述】:

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

#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;
         }
      }
};

我想为每个枚举值专门化 getSound 函数,以摆脱开关盒。这样的模板特化可能吗?

【问题讨论】:

    标签: c++ templates sfinae specialization


    【解决方案1】:

    是的,这是可能的。请看下面的示例。

    #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>();
    }
    

    【讨论】:

    • 谢谢 S.M.为您的回应。这解决了我的查询。接受它作为答案。
    【解决方案2】:

    我不明白你为什么要转专业。如果此示例是指示性的,并且您的枚举器是顺序的并且从 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
    }
    

    【讨论】:

    • 感谢您的回复。这只是一个指示性例子。案件内部发生了一堆处理。这就是为什么我们要使用专业化。我已编辑问题以反映这一点。
    • @vchandra - 这仍然不会取消查找表的资格。等一下
    • 抱歉我的回复晚了。非常感谢您花时间为我提供不同的解决方案。我从这个答案中学到了很多东西。我正在接受 S.M. 的回答。因为它更接近我关于模板专业化的原始问题。再次感谢。
    猜你喜欢
    • 2010-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-11
    • 1970-01-01
    • 2018-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多