#include <iostream>
#include <boost/shared_ptr.hpp>
struct num_ {
virtual ~num_() {}
virtual bool is_zero() const = 0;
};
typedef const boost::shared_ptr<const num_> num;
struct zero_ : public num_ {
bool is_zero() const { return true; }
};
struct inc_ : public num_ {
num n_;
inc_(num n) : n_(n) {}
bool is_zero() const { return false; }
};
num zero() { return num(new zero_); }
num inc(num n) { return num(new inc_(n)); }
num dec(num n) { return boost::dynamic_pointer_cast<const inc_> (n)->n_; }
num operator+ (num n1, num n2) {
return
n1->is_zero() ? n2 :
n2->is_zero() ? n1 :
inc(n1) + dec(n2);
}
num operator- (num n1, num n2) {
return
n1->is_zero() ? n1 :
n2->is_zero() ? n1 :
dec(n1) - dec(n2);
}
int to_int(num n) {
return n->is_zero() ? 0 : to_int(dec(n)) + 1;
}
std::ostream& operator<< (std::ostream &s, num n) {
return s << to_int(n);
}
int main()
{
std::cout << inc(inc(inc(zero()))) + inc(inc(zero())) << std::endl;
return 0;
}