Is it possible to specialize a class method for individual enum values? Specifically I have an enum and a class as follows:
#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;
}
}
};
I want to specialize getSound function for each of the enum values to get rid of the switch case. Is such template specialization possible?
Yes, it is possible. Look at the sample below.
#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>();
}
I don't see why you want to go for specialization. If this example is indicative and your enumnerators are sequential and starting from 0, you can just use a lookup 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));
}
And that's it. It also replaces the the "unknown"
string by an exception being thrown. I feel this is warranted, since a scoped enumeration implies we expect strict checking of the value being passed. And breaking that is an exceptional situation.
Even your edited question can be subjected to a lookup 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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With