B
Wieso es zwei Parameter sein müssen kannst Du im Kommentar der main()-Funktion nachlesen
// Klasse um das Verhalten der Vergleichsoperatoren zu steuern.
template <class T>
struct IConditionOperand
{
private:
T value_;
public:
T value();
bool operator ==(IConditionOperand<T> * co) { return value_ == co->value_; }
bool operator !=(IConditionOperand<T> * co) { return value_ != co->value_; }
bool operator <(IConditionOperand<T> * co) { return value_ < co->value_; }
bool operator <=(IConditionOperand<T> * co) { return value_ <= co->value_; }
bool operator >(IConditionOperand<T> * co) { return value_ > co->value_; }
bool operator >=(IConditionOperand<T> * co) { return value_ >= co->value_; }
IConditionOperand(T v) : value_(v) {}
};
// Andere Möglichkeit, über deren Sinn sich streiten lässt. Aber Zweck vor Sinn!
template <class T>
struct NegConditionOperand : public IConditionOperand<T>
// Alle Vergleiche werden umgedreht
{
NegConditionOperand(T value) : IConditionOperand<T>(value){}
bool operator ==(NegConditionOperand<T> * co) { return value_ != co->value_; }
bool operator !=(NegConditionOperand<T> * co) { return value_ == co->value_; }
bool operator <(NegConditionOperand<T> * co) { return value_ >= co->value_; }
bool operator <=(NegConditionOperand<T> * co) { return value_ > co->value_; }
bool operator >(NegConditionOperand<T> * co) { return value_ <= co->value_; }
bool operator >=(NegConditionOperand<T> * co) { return value_ < co->value_; }
};
template < class T >
class ICondition
{
public:
enum Type { equal, notEqual, less, lessOrEqual, greater, greaterOrEqual };
private:
IConditionOperand<T> * left_;
IConditionOperand<T> * right_;
Type t_;
public:
ICondition() : left_(NULL), right_(NULL){};
void setLeft(IConditionOperand<T> * l){
if(left_)
delete left_;
left_ = l;
}
void setRight(IConditionOperand<T> * r){
if(left_)
delete right_;
right_ = r;
}
void setOperator(Type t) {
t_ = t;
}
virtual bool test() {
switch(t_){
case equal: return (* left_) == right_;
case notEqual: return (* left_) != right_;
case less: return (* left_) < right_;
case lessOrEqual: return (* left_) <= right_;
case greater: return (* left_) > right_;
case greaterOrEqual: return (* left_) >= right_;
default: return false;
}
}
};
#pragma argsused
int main(int argc, char* argv[])
{
// dann irgendo wird alles aufgerufen
ICondition<int> c;
c.setLeft(new NegConditionOperand<int>(20));
c.setRight(new NegConditionOperand<int>(20));
c.setOperator(ICondition<int>::equal);
cout << "(20 == 20) ist ";
if ( c.test() ){ /* Aus irgendeinem Grund wird operator ==() von
IConditionOperand aufgerufen deswegen dachte ich,
dass wenn man den Typ übergibt, dass dann auch die
richtige Funktion aufgerufen wird. */
cout << "wahr";
} else {
cout << "falsch";
}
getch();
return 0;
}
Der Sinn des ganzen ist (man könnte schließlich auch if (20 == 20) { cout << "wahr"; } else { cout << "falsch"; }), dass die if-Schleife(n) zur Laufzeit geparst wird. Templates sind dazu da, weil alle Typen schon zur Compilierzeit bekannt sind.