#include <iostream>
#include <limits>

//#include <boost/integer_traits.hpp>
#define BOOST_STATIC_ASSERT(x)

template<long x, bool valid = true> struct maybe_num;
template<long x> struct maybe_num<x, false> {
    static const bool ok = false;
};
template<long x> struct maybe_num<x, true> {
    static const bool ok = true;
    static const long value = x;
};

// A binary operator lifted to the maybe_num type; the result is 'not
// ok' if either of the inputs were.  Inherit from this and provide
// your own specialization for the case where both inputs are ok.
//

// Instead of this 'result' member I thought about just inheriting
// from maybe_num<0, false> or whatever the result of the computation
// is.  But I think you need the member selection to force the
// evaluation, otherwise it's just like pasting macros and the
// compiler complains it cannot find a specialization for
// plus<plus<..., ...>, ...>.
//
template<class X, class Y> struct binop_maybe;
template<long x, long y>
struct binop_maybe<maybe_num<x, false>, maybe_num<y, false> > {
    typedef maybe_num<0, false> result;
};
template<long x, long y>
struct binop_maybe<maybe_num<x, false>, maybe_num<y, true> > {
    typedef maybe_num<0, false> result;
};
template<long x, long y>
struct binop_maybe<maybe_num<x, true>, maybe_num<y, false> > {
    typedef maybe_num<0, false> result;
};
template<long x, long y>
struct binop_maybe<maybe_num<x, true>, maybe_num<y, true> > {};

// Similarly for unary operators.
template<class X> struct unop_maybe;
template<long x> struct unop_maybe<maybe_num<x, false> > {
    typedef maybe_num<0, false> result;
};
template<long x> struct unop_maybe<maybe_num<x, true> > {};

template<class X, class Y> struct plus :binop_maybe<X, Y> {};
template<long x, long y>
struct plus<maybe_num<x>, maybe_num<y> > {
    typedef maybe_num<x + y, (y >= 0) ? (x + y >= x) : (x + y < x)> result;
};

// General integer division not yet implemented.
template<class X> struct half :unop_maybe<X> {};
template<long x> struct half<maybe_num<x> > {
    typedef maybe_num<x / 2> result;
};

// Special case of multiplication, used to implement general
// multiplication below.
//
template<class X> struct twice :unop_maybe<X> {};
template<long x> struct twice<maybe_num<x> > {
    typedef maybe_num<x * 2, (x >= 0) ? (x * 2 >= x) : (x * 2 < x)> result;
};    

// General multiplication.
template<class X, class Y> struct times :binop_maybe<X, Y> {};
template<long x> struct times<maybe_num<x>, maybe_num<0> > {
    typedef maybe_num<0> result;
};
template<long x, long y> struct times<maybe_num<x>, maybe_num<y> > {
    BOOST_STATIC_ASSERT(y > 0);
    // assert also that half<maybe_num<y> > succeeds

    typedef typename plus<typename twice<typename times<maybe_num<x>, typename half<maybe_num<y> >::result >::result>::result, maybe_num<(y % 2) * x> >::result result;
};

int main()
{
    std::cout << plus<maybe_num<3>, maybe_num<-4> >::result::value << std::endl;
    std::cout << times<maybe_num<3000>, maybe_num<300000> >::result::value << std::endl;
//    const long m = boost::integer_traits<long>::const_max;
//    std::cout << plus<maybe_num<m>, maybe_num<m> >::result::ok << std::endl;
}
