#include <boost/any.hpp>
#include <string>
#include <iostream>
#include <typeinfo>

template <class T>
T max(const T& a, const T& b)
{
  return (a>b?a:b);
}

class BadType{
public:
  BadType(std::string t1,std::string t2):typ1(t1),typ2(t2) {}
private:
  std::string typ1;
  std::string typ2;
};
  
template <class T, class R>
class MyAny {
public:
  MyAny(boost::any a,std::string typ):val(a),tip(typ) {}

  operator T() const
  {
    if (tip==std::string(typeid(T).name()))
      return boost::any_cast<T>(val);
    else throw BadType(typeid(T).name(),typeid(R).name());
  }

  operator R() const 
  {
     if (tip==std::string(typeid(R).name())) 
       return boost::any_cast<R>(val);
     else throw BadType(std::string(typeid(T).name()),std::string(typeid(R).name()));
  }

  boost::any value() const { return val;}
  std::string type() const { return tip;}
  

private:
  boost::any val;
  std::string tip;
};

template <class T, class R>
std::ostream& operator<<(std::ostream& st, const MyAny<T,R>& x) {
  if (x.type()==std::string(typeid(T).name())) 
    st << boost::any_cast<T>(x.value());
  if (x.type()==std::string(typeid(R).name())) 
    st << boost::any_cast<R>(x.value());
  return st;
}

template <class T, class R>
MyAny<T,R> max(const T& a, const R& b) {
  return(a>b ? MyAny<T,R>(a,typeid(a).name()):MyAny<T,R>(b,typeid(b).name()));
}

int main() {
  int i=14;
  double d=6.7;
  std::cout << max(d,i) << std::endl;

  return 0;
}