交换两个 boost::adjacency_list 图,类似于 std::swap

Swapping two boost::adjacency_list graphs, akin to std::swap

我正在构建一个应用程序,其中包含 class DecoratedGraph(比如说)使用 boost::adjacency_list graph 作为基础成员。

我在 DecoratedGraph 中也有一些其他成员,其中一些成员将 std::mapstd::vector 存储在 graphvertices 上,代表各种附加属性。我将这些附加属性称为 decorations.

我写了一个自定义复制构造函数,它不仅会复制图形,还会确保 decorations 引用 上的顶点,已复制图,非原图

根据 Rule of 3,除了复制构造函数,我们还需要复制赋值运算符和析构函数的定义 - 所以我也一直在实现这些。

对于复制赋值运算符,我使用了 another Whosebug answer 建议的复制和交换习惯用法。要为我的 class 实现交换功能,我需要同时交换 graphdecorations。目前,我已经使用 std::map::swapstd::vector::swap 交换了 decorations,并使用 std::swap 交换了两个对象的其他成员,包括 graph .

然而,当我尝试在交换对象上使用 decorations 时,我发现引用不再引用 graph 上的顶点。我不确定我哪里出错了:我认为问题很可能在于 swap 函数没有按我预期的那样运行。 deocrations 上使用的 swap 分别是 std::mapstd::vector 的成员方法——我希望它们能按预期运行。我怀疑可能有问题的地方是 std::swapboost::adjacency_list 对象上的使用,这可能会产生意外行为。

我想知道 std::swap 是否是交换两个 boost::adjacency_list graph 的正确方法?如果不是,正确的方法是什么?

的确,std::swap好像不是你想要的。它选择 the generic std::swap 通过临时的、非常简化的实现:

template <typename T> inline void swap(T& a, T& b) {
    T tmp = std::move(a);
    a = std::move(b);
    b = std::move(tmp);
}

这看起来不错,除了 Boost Graph 很大程度上早于 C++11,所以 actuvely 不使用移动语义。 adjacency_list<>::swap 成员的实现就是例证:

void swap(adjacency_list& x)
{
    // Is there a more efficient way to do this?
    adjacency_list tmp(x);
    x = *this;
    *this = tmp;
}

他们甚至不假装尝试移动。

做什么

根据您的装饰方式,您可能会使用 copy_graph 免费获得 home-run,它将复制内部属性以及捆绑属性和图形属性。

您需要手动复制外部 property maps(或您的 home-grown 等效项)。

Out-Of-The 盒子

使交换便宜 原子(考虑异常安全性!)的传统方法是使用 Pimpl 惯用语并仅交换实现指针。