To demonstrate, imagine that I have some classes of animals, each of which is derived from the class of "animals", each of which "knows" what type they are, and each of which has its own unique ability:
enum class animal_type { antelope, bear, cat };
class animal
{
};
class antelope : public animal
{
public:
static const animal_type type = animal_type::antelope;
void run() { std::cout << "antelope runs\n"; };
};
class bear : public animal
{
public:
static const animal_type type = animal_type::bear;
void roar() { std::cout << "bear roars\n"; };
};
class cat : public animal
{
public:
static const animal_type type = animal_type::cat;
void meow() { std::cout << "cat meows\n"; };
};
Now I want to be able to get animals by their type:
class animal_getter
{
public:
animal& get(animal_type t)
{
static antelope s_antelope;
static bear s_bear;
static cat s_cat;
switch (t)
{
case animal_type::antelope:
return s_antelope;
case animal_type::bear:
return s_bear;
case animal_type::cat:
return s_cat;
}
}
};
And finally, it would be nice to get the real type of animal back to make the call syntax more enjoyable:
template<typename T>
T& get()
{
return static_cast<T&>(get(T::type));
}
Now I can write something like this:
animal_getter ag;
ag.get<antelope>().run();
not wordier:
animal_getter ag;
static_cast<antelope&>(ag.get(animal_type::antelope)).run();
, . unit test , animal_getter (, -, unit test, , ). "get get", , . , ? :
struct IAnimalGetter
{
virtual template<typename T> T& get() = 0;
};
, ?
, ? , ? -, , ?