簡體   English   中英

boost 圖形庫,depth_first_search 不調用 msvc 中的 finish_edge

[英]boost graph library, depth_first_search not calling finish_edge in msvc

我正在使用 Boost 1.70.0,與 vs-2017。 使用depth_first_search我觀察到使用 msvc 編譯器編譯時不會調用訪問者中的finish_edge函數。 在 gcc (8.3) 中, finish_edge函數被正確調用

示例代碼:

struct DfsVisitor : public boost::default_dfs_visitor
{
    template <class Graph>
    void
    finish_edge(typename Graph::edge_descriptor ed, const Graph& g)
    {
        std::cout << "Finish edge " << boost::source(ed, g) << "->" << boost::target(ed, g) << std::endl;
    }
};

DfsVisitor dfs;
boost::depth_first_search(g, boost::visitor(dfs)); // g is graph, adjacency_list

您是否有一個 SSCCE,我們可以實際運行它來觀察行為? 這樣會節省很多時間

我就是這樣做的:就是這樣做的:在 msvc 上重現Boost 1.60

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/depth_first_search.hpp>
#include <iostream>

struct DfsVisitor : public boost::default_dfs_visitor {
    template <class Graph> void finish_edge(typename Graph::edge_descriptor ed, const Graph &g) {
        std::cout << "Finish edge " << boost::source(ed, g) << "->" << boost::target(ed, g) << std::endl;
    }
};

int main() {
    boost::adjacency_list<> g(4);
    add_edge(0,1,g);
    add_edge(1,2,g);
    add_edge(2,3,g);

    DfsVisitor dfs;
    boost::depth_first_search(g, boost::visitor(dfs));

    std::cout << "Done\n";
}

只是打印:

Done

為了比較,

所以顯然它與 boost 版本的關系比編譯器更相關。 Godbolt 不會比 Boost 1.64 更遠(仍然可以: https ://godbolt.org/z/Ld8-8d)但 wandbox 確實:

檢查Boost 1.62.0發行說明似乎沒有提到什么,但使用 github 歷史確實發現:

$ git clone https://github.com/boostorg/graph
$ cd graph
$ git log --oneline --graph --left-right --cherry-pick boost-1.61.0...boost-1.62.0 | grep -i finish
> a14f8df8 Fixed bug 10231 partly: If finish_edge was called, then now correctly. (#16)
> d6b7a717 Add finish_edge test case from Alex Lauser.
> 6a2d45ae Condition TTI finish_edge on supported compilers.
> 0e1414f4 Fix type traits so finish_edge is called when defined.

我在 boost-1.70 和 VS-2013 (x64, 18.00) 上遇到了同樣的問題。 查看boost中的實現,其他編譯器的實現與 GCC、Clang 或 Intel 編譯器不同:

    template <typename E, typename G, typename Vis>
    void call_finish_edge(Vis& vis, E e, const G& g) { // Only call if method exists
#if ((defined(__GNUC__) && (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9))) || \
    defined(__clang__) || \
    (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1200)))
    do_call_finish_edge<
        has_member_function_finish_edge<Vis, void,
        boost::mpl::vector<E, const G&> >::value>::call_finish_edge(vis, e, g);
#else
    do_call_finish_edge<has_member_function_finish_edge<Vis, void>::value>::call_finish_edge(vis, e, g);
#endif
    }

對於其他編譯器,調用方法has_member_function_finish_edge (由宏BOOST_TTI_HAS_MEMBER_FUNCTION(finish_edge) )時,參數不會作為模板參數給出

所以我們可以通過添加另一個不帶參數的空方法來讓 boost 檢測它:

template <class Edge, class Graph>
void finish_edge(Edge e, Graph& g) {
     std::cout << "finish_edge e=" << e << std::endl;
} 

void finish_edge() {}

空方法永遠不會被調用,但足以讓 boost 檢測到它。 不必這樣做就好了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM