#include <iostream>
template<typename C, typename T>
struct caster;
template<typename C>
struct caster<C, long>
{
static long cast(const C& c) { return c.as_long(); }
};
template<typename C>
struct caster<C, double>
{
static double cast(const C& c) { return c.as_double(); }
};
template<typename C, typename T>
struct ops_base
{
friend bool operator==(const ops_base& l, const ops_base& r)
{
const C& cl = static_cast<const C&>(l);
const C& cr = static_cast<const C&>(r);
return (caster<C, T>::cast(cl) == caster<C, T>::cast(cr));
}
friend bool operator==(const ops_base& l, T r)
{
const C& cl = static_cast<const C&>(l);
return (caster<C, T>::cast(cl) == r);
}
friend bool operator==(T l, const ops_base& r)
{
const C& cr = static_cast<const C&>(r);
return (l == caster<C, T>::cast(cr));
}
friend bool operator!=(const ops_base& l, const ops_base& r)
{ return !(l == r); }
friend bool operator!=(const ops_base& l, T r)
{ return !(l == r); }
friend bool operator!=(T l, const ops_base& r)
{ return !(l == r); }
friend bool operator<(const ops_base& l, const ops_base& r)
{
const C& cl = static_cast<const C&>(l);
const C& cr = static_cast<const C&>(r);
return (caster<C, T>::cast(cl) < caster<C, T>::cast(cr));
}
friend bool operator<(const ops_base& l, T r)
{
const C& cl = static_cast<const C&>(l);
return (caster<C, T>::cast(cl) < r);
}
friend bool operator<(T l, const ops_base& r)
{
const C& cr = static_cast<const C&>(r);
return (l < caster<C, T>::cast(cr));
}
friend bool operator>(const ops_base& l, const ops_base& r)
{
const C& cl = static_cast<const C&>(l);
const C& cr = static_cast<const C&>(r);
return (caster<C, T>::cast(cl) > caster<C, T>::cast(cr));
}
friend bool operator>(const ops_base& l, T r)
{
const C& cl = static_cast<const C&>(l);
return (caster<C, T>::cast(cl) > r);
}
friend bool operator>(T l, const ops_base& r)
{
const C& cr = static_cast<const C&>(r);
return (l > caster<C, T>::cast(cr));
}
friend bool operator<=(const ops_base& l, const ops_base& r)
{ return !(l > r); }
friend bool operator<=(const ops_base& l, T r)
{ return !(l > r); }
friend bool operator<=(T l, const ops_base& r)
{ return !(l > r); }
friend bool operator>=(const ops_base& l, const ops_base& r)
{ return !(l < r); }
friend bool operator>=(const ops_base& l, T r)
{ return !(l < r); }
friend bool operator>=(T l, const ops_base& r)
{ return !(l < r); }
};
template<typename C, typename T>
struct io_base
{
friend std::ostream& operator<<(std::ostream& out, const io_base& self)
{
const C& c = static_cast<const C&>(self);
return out << caster<C, T>::cast(c);
}
};
struct Long : ops_base<Long, long>, io_base<Long, long>
{
Long(long val) : value_(val) { }
long as_long() const { return value_; }
private:
long value_;
};
struct Float : ops_base<Float, double>, io_base<Float, double>
{
Float(double val) : value_(val) { }
double as_double() const { return value_; }
private:
double value_;
};
int main(int argc, char** argv)
{
{
Long l { 5 };
Long r { 6 };
std::cout << "[Long, Long]" << std::endl;
std::cout << l << " == " << r << " : " << (l == r) << std::endl;
std::cout << l << " != " << r << " : " << (l != r) << std::endl;
std::cout << l << " < " << r << " : " << (l < r) << std::endl;
std::cout << l << " > " << r << " : " << (l > r) << std::endl;
std::cout << l << " <= " << r << " : " << (l <= r) << std::endl;
std::cout << l << " >= " << r << " : " << (l >= r) << std::endl;
}
{
Long l { 5 };
long r { 6 };
std::cout << "[Long, long]" << std::endl;
std::cout << l << " == " << r << " : " << (l == r) << std::endl;
std::cout << l << " != " << r << " : " << (l != r) << std::endl;
std::cout << l << " < " << r << " : " << (l < r) << std::endl;
std::cout << l << " > " << r << " : " << (l > r) << std::endl;
std::cout << l << " <= " << r << " : " << (l <= r) << std::endl;
std::cout << l << " >= " << r << " : " << (l >= r) << std::endl;
}
{
Float l { 5 };
Float r { 6 };
std::cout << "[Float, Float]" << std::endl;
std::cout << l << " == " << r << " : " << (l == r) << std::endl;
std::cout << l << " != " << r << " : " << (l != r) << std::endl;
std::cout << l << " < " << r << " : " << (l < r) << std::endl;
std::cout << l << " > " << r << " : " << (l > r) << std::endl;
std::cout << l << " <= " << r << " : " << (l <= r) << std::endl;
std::cout << l << " >= " << r << " : " << (l >= r) << std::endl;
}
{
Float l { 5 };
float r { 6 };
std::cout << "[Float, float]" << std::endl;
std::cout << l << " == " << r << " : " << (l == r) << std::endl;
std::cout << l << " != " << r << " : " << (l != r) << std::endl;
std::cout << l << " < " << r << " : " << (l < r) << std::endl;
std::cout << l << " > " << r << " : " << (l > r) << std::endl;
std::cout << l << " <= " << r << " : " << (l <= r) << std::endl;
std::cout << l << " >= " << r << " : " << (l >= r) << std::endl;
}
}