通过异常终止增强图搜索的原因是什么?

What were the reasons to terminate boost graph searches via exceptions?

根据FAQ:

,广度优先搜索等boost图中算法的提前退出应该通过抛出异常来完成
  1. How do I perform an early exit from an algorithm such as BFS?

    Create a visitor that throws an exception when you want to cut off the search, then put your call to breadth_first_search inside of an appropriate try/catch block. This strikes many programmers as a misuse of exceptions, however, much thought was put into the decision to have exceptions has the preferred way to exit early. See boost email discussions for more details.

我对实际的“做出决定的想法”感兴趣。到目前为止,我未能在邮件列表中找到合适的 posts。我找到的最接近的是 this one,说明

If the graph is big, exiting the algorithm by throwing an exception might be the most efficient way ;-). Of course, if you do many invocations on small graphs, it may be the least efficient ;-(.

this one:

If you have enough callbacks, you can surely do all the same things. I'm not sure what loss of control you fear, but from an efficiency point-of-view it might make sense to exit the algorithm by throwing an exception (no, I'm really NOT kidding).

对我来说,这并不是设计决策的真正有根据的理由。也因为当抛出大量异常时,我们确实看到了巨大的减速,尤其是当 运行 调试器中的代码时。 我也知道 Whosebug 上的类似 posts(例如 this one or this one)询问 如何 来终止搜索。但我知道如何(通过抛出异常)。然而,none 提供了决定背后的原因。

所以我的问题是:有人知道做出决定的实际想法吗?有没有人有实际的 link 到 boost 邮件列表 post,其中包含常见问题解答中提到的这些想法?

它简化了实现。它允许所有搜索利用通用遍历算法。

面对仿制药,争论变得更加激烈。

请注意,访问者可以通过多种方式实现:

  • 用户可以实现访客界面
  • 从一个派生并覆盖一些处理程序

特别是如果处理程序要 return 控制值,这种情况会产生具有通用组合的问题。如果多个处理程序处理同一个事件,return 值将如何组合?

This situation is similar to other event-driven designs, like browser script UI events (which can bubble up or not) or Boost Signals2 signal slots, which can have user-supplied combiners instead of the default optional_last_value

关键要素是事件处理程序/“插槽”的多样性。

您可能会争辩说,这可以概括为“图书馆不提供提前终止搜索”,但由于文档反映了设计者特别选择允许在此处使用异常语言功能。除了您已经提到的所有地方之外,让我引用 BGL 函数 is_bipartite 的实现,该函数使用当图不是二分图时可能过早中止的 DFS:

try
{
    depth_first_search(graph,
        vertex_index_map(index_map).visitor(make_dfs_visitor(
            std::make_pair(detail::colorize_bipartition(partition_map),
                std::make_pair(detail::check_bipartition(partition_map),
                    put_property(partition_map,
                        color_traits< partition_color_t >::white(),
                        on_start_vertex()))))));
}
catch (const detail::bipartite_visitor_error< vertex_descriptor_t >&)
{
    return false;
}

return true;