Hi Jeff,
The worst of all possible worlds is to test the argument's run-time type
with a switch statement, if-else block, or the like (the "switch on
type" approach).
The next worst of all possible worlds is to code a different version of
the function for each derived type that may be an argument to it (the C
approach).
Hmm, this leads me to the next question:
given the case you have to call a function depending on two Instances of a
class, what shall we do then?
I append a small example to demonstrate you the Problem I have. Additionally
there is another constraint: no function overloading (a real-world reason
:-( ) for the final function "kicking" which is called out of main.
Please take a closer look at the function kicking. The if..else table is a
real horror. But how to solve it in an easier way?
Regards,
Patrick
// CODE STARTS
#include <iostream>
// small hierachy
// abstact base class, virtual for RTTI
class mama {
protected:
mama() {};
virtual ~mama() {};
};
class daughter : public mama {};
class son : public mama {};
class son2 : public mama {};
// small action functors
template <typename T1,typename T2> struct kick;
template <typename T> struct kick<T,T>
{
void operator()() { std::cout << "Look mum, I am kicking me." <<
std::endl; }
};
template <> struct kick<son,daughter>
{
void operator()() { std::cout << "He, do not kick girls !!!" <<
std::endl; }
};
template <> struct kick<son2,daughter>
{
void operator()() { std::cout << "He, do not kick girls !!!" <<
std::endl; }
};
template <> struct kick<daughter,son>
{
void operator()() { std::cout << "Aua, that hurts." << std::endl; }
};
template <> struct kick<daughter,son2>
{
void operator()() { std::cout << "Aua, that hurts." << std::endl; }
};
template <> struct kick<son,son2>
{
void operator()() { std::cout << "son2 is crying running to mama" <<
std::endl; }
};
template <> struct kick<son2,son>
{
void operator()() { std::cout << "son is kicking back" << std::endl; }
};
// function which shall be executed
// uuuuuhhhhh, this is really ugly,
// just for a call kick<instancetype(fam1_),instancetype(fam2_)>()();
// I really expect typos
void kicking(const mama & fam1_,const mama & fam2_)
{
std::cout << typeid(fam1_).name() << " tries to kick ";
std::cout << typeid(fam2_).name() << ": ";
if ( typeid(daughter) == typeid(fam1_) )
if ( typeid(daughter) == typeid(fam2_) )
kick<daughter,daughter>()();
else if ( typeid(son) == typeid(fam2_) )
kick<daughter,son>()();
else if ( typeid(son2) == typeid(fam2_) )
kick<daughter,son2>()();
else throw "Ups, what happend ?";
else if ( typeid(son) == typeid(fam1_) )
if ( typeid(daughter) == typeid(fam2_) )
kick<son,daughter>()();
else if ( typeid(son) == typeid(fam2_) )
kick<son,son>()();
else if ( typeid(son2) == typeid(fam2_) )
kick<son,son2>()();
else throw "Ups, what happend ?";
else if ( typeid(son2) == typeid(fam1_) )
if ( typeid(daughter) == typeid(fam2_) )
kick<son2,daughter>()();
else if ( typeid(son) == typeid(fam2_) )
kick<son2,son>()();
else if ( typeid(son2) == typeid(fam2_) )
kick<son2,son2>()();
else throw "Ups, what happend ?";
else throw "Ups, what happend ?";
}
// examples
int main()
{
kicking( son() , daughter() );
kicking( daughter() , son() );
kicking( son() , son() );
kicking( son() , son2() );
kicking( son2() , son() );
kicking( son2() , daughter() );
return 0;
}
// CODE ENDS