The shape design problem

If you are working with an already existing large code base then you go where that code base leads you. I was answering the OP’s question, which involved starting a new code base involving a Point, a Rectangle and a Circle and two behaviors on them (area and draw). One additional requirement was “You should be able to isolate change in the system”, in connection with two questions: “How easy would it be to add a new shape, say, triangle?” and “How easy would it be to add a new behaviour to all shapes, like save/load from a SQL database?”

So the question about isolating change becomes: Which change is predominant – additional shapes or additional behaviors? Your approach is more suitable to the first. Sure, your latest example adds a new behavior without controversy but this was a weak example - you were able to leverage the various to_string functions that the standard library already provides for ints, floats and bools. ints, floats and bools are not shapes. To stringify shapes you would have to revise each shape module to add an equivalent function in order to construct a first class module to which to apply your Stringable.create function. With variants you can write a generic to_string function for all the shapes of interest in one go.

That’s the theory of it. Of course, in order to implement such a generic to_string function you may end up modifying other modules in other translation units anyway which somewhat muddies the waters. There is a world of trade-offs. This is well explored territory.