/* The original version of this program can be found at http://damb.dk */
#include <iostream>
#include <vector>
#include <stdexcept>
#include <typeinfo>

class BaseClass
{
public:
   enum ClassType
   {
      DoubleType,
      IntType
   };
   const ClassType Type;
   virtual ~BaseClass(){}
protected:
   BaseClass(ClassType aType) : Type(aType)
   {}
public:
   class DoubleClass *GetAsDoubleClass();
   class IntClass *GetAsIntClass();
private:
   BaseClass();
};

class DoubleClass : public BaseClass
{
public:
   DoubleClass(double aD) : BaseClass(DoubleType), D(aD)
   {}
   double D;
};

class IntClass : public BaseClass
{
public:
   IntClass(int aI) : BaseClass(IntType), I(aI)
   {}
   int I;
};

class DoubleClass *BaseClass::GetAsDoubleClass()
{
   if(Type != DoubleType)
   {
      throw std::bad_cast();
   }
   DoubleClass *Ret = dynamic_cast<DoubleClass *>(this);
   if(!Ret)
   {
      throw std::bad_cast();
   }
   return Ret;
}

class IntClass *BaseClass::GetAsIntClass()
{
   if(Type != IntType)
   {
      throw std::bad_cast();
   }
   IntClass *Ret = dynamic_cast<IntClass *>(this);
   if(!Ret)
   {
      throw std::bad_cast();
   }
   return Ret;
}

int main()
{
   std::vector<BaseClass *>MyVector;
   MyVector.push_back(new IntClass(123));
   MyVector.push_back(new DoubleClass(1.123));
   size_t i;

   for(i = 0; i < MyVector.size(); i++)
   {
      try
      {
         if(MyVector[i]->Type == BaseClass::IntType)
         {
            IntClass *Int = MyVector[i]->GetAsIntClass();
            std::cout << Int->I << std::endl;
            DoubleClass *Double = MyVector[i]->GetAsDoubleClass(); // Should throw
         }
         else
         {
            DoubleClass *Double = dynamic_cast<DoubleClass *>(MyVector.at(i));
            if(Double)
               std::cout << Double->D << std::endl;
            else
               std::cout << "Ups it was not a DoubleClass" << std::endl;
         }
      }
      catch (std::bad_cast e)
      {
         std::cout << "Ups, bad cast" << std::endl;
      }
   }
}