BGL edge(u, v, g) with custom associative containe

2019-05-11 08:34发布

I've just begun learning bgl and have hit on a problem while using a std::set with a custom ordering as the container for edge lists in an adjacency_list. I define the operator< to order the edges based on their properties, much like in the ordered_out_edges.cpp example. Here boost::edge_unique_ordering is a custom property tag.

template < typename Edge >
struct order_by_unique_order: public std::binary_function< Edge, Edge, bool >
{
    inline bool operator() (const Edge& e1, const Edge& e2) const
    {
        return boost::get(boost::edge_unique_ordering, e1) < boost::get(boost::edge_unique_ordering, e2);
    }
};

struct default_edge_containerS {};

namespace boost
{
    template < class ValueType >
    struct container_gen< default_edge_containerS, ValueType >
    {
        typedef std::set< ValueType, order_by_unique_order< ValueType > > type;
    };
}

In general it is working fine, but I am getting iterator exceptions when I use the edge(u, v, g) function. If I replace these calls with a workaround to avoid requesting edges by (source, target) then everything works fine.

I looked through the boost code and I'm pretty sure I know what the cause is, I'm just unsure if it means I'm doing something wrong, it's a problem with the boost code, or just an undocumented incompatibility. The function invokes set::find(StoredEdge(v)) on the out edge list container of u. Now the default stored_edge::operator< just compares target vertices, but in my case my custom operator< is being called, and the StoredEdge(v) which is being looked for is obviously default initialized with no properties, which presumably is the cause of the problem. It seems to me that edge(u, v, g) should be searching for any match based strictly on the target vertex, regardless of what ordering is imposed on the edges within the container.

Can anyone shed some light on what I may be doing wrong or not understanding?

1条回答
对你真心纯属浪费
2楼-- · 2019-05-11 09:09

It looks like you will need to write a wrapper comparison operator that takes a type (which will be filled in using the StoredEdge type) and compares the results of get_target) on the two inputs using your custom compare function, using something like:

template <typename Cmp>
struct target_compare {
  Cmp cmp;
  target_compare(const Cmp& cmp): cmp(cmp) {}
  template <typename SE>
  bool operator()(const SE& a, const SE& b) const {
    return cmp(a.get_target(), b.get_target());
  }
};

then use target_compare<order_by_unique_order<Edge> > as the comparison type in your set.

查看更多
登录 后发表回答