C++ exceptions are zero cost only when *not* thrown; keeping them out of critical paths can make a significant difference in performance.

Throwing exceptions is currently a routine part of the process of identifying concrete types for dispatching. When runtime is dominated by code strictly inside C++ this is not an issue, but for algorithms that must repeatedly cross the C++/Python boundary it can become a real performance problem. In particular, the search algorithms and their Visitors do this; I have found that using a non-throwing approach makes a dramatic speed improvement - over 2X for a maze router benchmark based on an implicit A* search.

I'm offering this patch as an implementation; I think it may be worth investigating if similar optimizations are available elsewhere in the code.

Best,
Jeff