#include <iostream>

class Rectangle
{
     public:
     Rectangle(double w = 0, double h = 0, double r = 0) : width(w), height(h), radius(r)
     {}

     double width;
     double height;
     double radius;
};

namespace traits
{
    template <typename P>
    struct operations
    {
        static void display(Rectangle const &, std::ostream &);
        static double area(Rectangle const &);
    };
    
    template <typename P, int N>
    struct access {};
}

namespace traits
{
    template <int N>
    struct access<Rectangle, N>
    {
        static double get(Rectangle const &);
    };
}

namespace traits
{
    template <>
    struct access<Rectangle, 0>
    {
        static double get(Rectangle const &rect)
        {
            return rect.width;
        }
    };
    
    template <>
    struct access<Rectangle, 1>
    {
        static double get(Rectangle const &rect)
        {
            return rect.height;
        }
    };
}

namespace traits
{
    template <>
    struct operations<Rectangle>
    {
        static void display(Rectangle const &rect, std::ostream &os)
        {
            os << "Width of rectangle: " << rect.width << std::endl;
            os << "Height of rectangle: " << rect.height << std::endl;
            os << "Area of rectangle: " << area(rect) << std::endl; 
        }
        static double area(Rectangle const& rect)
        {
            double width  =  access<Rectangle, 0>::template get<0>(rect);
            double height =  access<Rectangle, 1>::template get<1>(rect);
            
            return width * height;
        }
    };
}

template <int N, typename P>
static inline double get(P const &p)
{
    return traits::access<P, N>::get(p);
}

template <typename P>
static inline void display(P const &p)
{
    traits::operations<P>::display(p, std::cout);
}

template <typename P>
static inline double area(P const &p)
{
    return traits::operations<P>::area(p);
}

/*ostream & operator<<(ostream & out, Shape const& s)
{
      s.display(out);
      return out;
}*/


int main()
{
    
}