枚举值的模板特化
Template specialization for enum values
是否可以为单个枚举值专门化一个 class 方法?
具体来说,我有一个枚举和一个 class 如下:
#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 函数以摆脱 switch case。这样的模板专业化可能吗?
我不明白你为什么要专攻。如果此示例是指示性的并且您的枚举器是连续的并且从 0 开始,您可以只使用查找 table:
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"
字符串。我觉得这是有道理的,因为范围枚举意味着我们期望对传递的值进行严格检查。打破 是 一个例外情况。
甚至您编辑的问题也可以进行查找 table:
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
}
是的,这是可能的。请看下面的示例。
#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>();
}
是否可以为单个枚举值专门化一个 class 方法? 具体来说,我有一个枚举和一个 class 如下:
#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 函数以摆脱 switch case。这样的模板专业化可能吗?
我不明白你为什么要专攻。如果此示例是指示性的并且您的枚举器是连续的并且从 0 开始,您可以只使用查找 table:
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"
字符串。我觉得这是有道理的,因为范围枚举意味着我们期望对传递的值进行严格检查。打破 是 一个例外情况。
甚至您编辑的问题也可以进行查找 table:
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
}
是的,这是可能的。请看下面的示例。
#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>();
}