Skip to content

Instantly share code, notes, and snippets.

@rsbowman
Last active August 29, 2015 14:23
Show Gist options
  • Save rsbowman/e788740b2883c179851f to your computer and use it in GitHub Desktop.
Save rsbowman/e788740b2883c179851f to your computer and use it in GitHub Desktop.
Simple Envelope/Letter Pattern
#include <iostream>
#include <memory>
using namespace std;
class Real;
class Integer;
class Number {
friend Real;
friend Integer;
public:
Number() {}
virtual Number add(const Number &n) const;
virtual Number realAdd(const Number &) const;
virtual Number intAdd(const Number& n) const;
virtual void print() const;
static Number makeReal(float r);
static Number makeInt(int v);
protected:
unique_ptr<Number> rep;
};
class Real : public Number {
friend Integer;
friend Number;
float val;
Real(float r) : val(r) {}
virtual Number add(const Number &n) const;
virtual Number realAdd(const Number &) const;
virtual Number intAdd(const Number& n) const;
virtual void print() const;
};
class Integer : public Number {
friend Real;
friend Number;
int val;
Integer(int n) : val(n) {}
virtual Number add(const Number &n) const;
virtual Number realAdd(const Number &) const;
virtual Number intAdd(const Number& n) const;
virtual void print() const;
};
Number Number::add(const Number& n) const {
return rep->add(n);
}
Number Number::realAdd(const Number& n) const {
return rep->realAdd(n);
}
Number Number::intAdd(const Number& n) const {
return rep->intAdd(n);
}
Number Number::makeReal(float f) {
Number n;
n.rep.reset(new Real(f));
return n;
}
Number Number::makeInt(int v) {
Number n;
n.rep.reset(new Integer(v));
return n;
}
void Number::print() const {
rep->print();
}
Number Real::add(const Number& n) const {
return n.realAdd(*this);
}
Number Real::realAdd(const Number& n) const {
const Real *rn = dynamic_cast<const Real *>(&n);
return Number::makeReal(this->val + rn->val);
}
Number Real::intAdd(const Number& n) const {
const Integer *it = dynamic_cast<const Integer *>(&n);
return Number::makeReal(this->val+ it->val);
}
void Real::print() const {
cout << "R(" << val << ")";
}
Number Integer::add(const Number& n) const {
return n.intAdd(*this);
}
Number Integer::intAdd(const Number& n) const {
const Integer *it = dynamic_cast<const Integer *>(&n);
return Number::makeInt(this->val+ it->val);
}
Number Integer::realAdd(const Number& n) const {
const Real *rn = dynamic_cast<const Real *>(&n);
return Number::makeReal(this->val + rn->val);
}
void Integer::print() const {
cout << "I(" << val << ")";
}
void print_sum(Number& n1, Number& n2) {
n1.print(); cout << " + "; n2.print();
cout << " = "; n1.add(n2).print();
cout << endl;
}
int main(void) {
Number i1 = Number::makeInt(5);
Number i2 = Number::makeInt(11);
Number r1 = Number::makeReal(3.14);
Number r2 = Number::makeReal(0.5);
print_sum(i1, i2);
print_sum(i1, r1);
print_sum(r2, i1);
print_sum(r1, r2);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment