I think there are some other considerations to bear in mind, which were briefly touched on last night.
To what extent can the problem of dispatch be dealt with implicitly? What I'm getting at here is that in some instances an appropriate concept could do the trick. For example, consider the simple cases where the weights are
(i) int
(ii) unsigned int
There is enough info to always correctly and optimally dispatch case (ii). The first case is harder. In general, we can't assume that Dijskstra will work and so by default we should dispatch to e.g. Bellman-Ford. However, clients may wish to explicitly override this if they know that none of the weights are actually negative.
Perhaps this implies a set of functions
shortest_path (constrained to accept graph-like types satisfying enough requirements for implicit dispatch)
shortest_path_semi_positive_weights (ideally with a nicer name)
shortest_path_negative_weights (ditto)
Oliver
PS Out of curiosity, what is your objection to overload sets? I tend to find them easier to work with in generic code since it's easy to create maps from types to types. However, I typically find maps from types to function invocations more fiddly and a bit clumsier.