
Wouldn't a typically C++-like approach be to use traits to ask each shape to present itself as an ellipse if it can?
ellipse_traits<X>::get_length() and ellipse_traits<X>::get_width() would give the length and width that X has when viewed as an ellipse. ellipse_traits<ellipse> would simply define them as being its length and width. ellipse_traits<circle> would define them as both being its radius. specialization ellipse_traits<rectangle> would not exist, meaning that a rectangle is-not-an ellipse. ellipse and circle would obviously be 2 completely separated classes.
Do you think this approach is valid and could be generalized to all geometric shapes?
Now you have way to state "X can be viewed as an ellipse". But how would you state "if X can be viewed as a circle, then it can be viewed as an ellipse (in the way that ellipse_traits<X>::get_width() returns circle_traits<X>::get_radius()"?