gpt4 book ai didi

c++ - 使用std::unique_ptr boost 图形捆绑属性

转载 作者:行者123 更新时间:2023-12-02 10:14:06 25 4
gpt4 key购买 nike

This answerstd::unique_ptr显示为带有boost-graph的 bundle 属性的成员。
提供的示例可以试用
Live On Coliru
因为我只对设计方面感兴趣,而不对答案的算法部分感兴趣,所以我提供了一个简化示例 Live On Coliru

#include <iostream>
#include <fstream>

#include <boost/graph/adjacency_list.hpp>

struct custom_node{
custom_node(std::string name, int capacity) : name(name), capacity(capacity) {}

std::string name = "uninitialized";
int capacity = -1;
};
void usage(){}

using namespace boost;

struct VertexProperties {
int id;
std::unique_ptr<custom_node> node;
};

typedef adjacency_list<vecS, vecS, directedS, VertexProperties> DirectedGraph;
typedef graph_traits<DirectedGraph>::vertex_descriptor custom_vertex;
typedef graph_traits<DirectedGraph>::edge_descriptor custom_edge;

int main() {
DirectedGraph g;

boost::add_vertex(g);
g[0].node = std::make_unique<custom_node>("inner", 2);

////boost::add_vertex(VertexProperties{0, std::make_unique<custom_node>("inner", 2)}, g); // compilation error

std::cout << boost::num_vertices(g);
std::cout << g[0].id << "\n";
std::cout << g[0].node->name << "\n";
std::cout << g[0].node->capacity << "\n";
}
可以通过 boost::add_vertex(g)添加顶点,然后可以实例化 std::unique_ptr
如果我尝试通过 add_vertex中的列表初始化通过创建具有所有属性的顶点来实现相同目的,则有关 implicitly-deleted copy constructor of 'VertexProperties'的编译错误。
当然, VertexProperties的副本构造函数已删除,因为 std::unique_ptr的副本构造函数已删除。
为什么拷贝构造函数对于列表初始化起初甚至是必需的?有什么我不了解的东西吗,或者这是升压曲线图的缺点?

最佳答案

Why is the copy constructor is necessary for list initialization in the first place? Is there something I do not understand about it, or is this a shortcoming of boost-graph?


那不是事情,也不是正在发生的事情。

Aside: in copy-initialization the assignment can be elided by the compiler, but operator= still needs to be accessible for it to be valid code.


但是在这种情况下,这只是库代码没有移动意识。您必须意识到“ bundle ”属性是分开存储的。 bundle 包(作为任何属性)无论如何都必须是默认可构造的(因此 add_vertex(g)可以工作),因此通过始终分配给默认构造的属性来简化实现。
由于它不是可移动的,因此赋值将不会转发右值,并且事物也不会编译。
选项
  • 链接的答案已经显示:
    if(g[v].node_logic) {
    g[v].node.reset(new custom_node(g[v].vertex_name, 0, standby, normal));
    }
  • 更多选项:
    VertexProperties props {0,
    std::make_unique<custom_node>("inner", 2)};
    auto vd = boost::add_vertex(g);
    g[vd] = std::move(props);
  • 收拾行情!您可以创建任何您喜欢的界面:
    auto add_vertex = [&g](VertexProperties&& props) {
    auto vd = boost::add_vertex(g);
    g[vd] = std::move(props);
    return vd;
    };

    add_vertex({0, std::make_unique<custom_node>("inner", 2)});
  • 您甚至可以详细说明:
    auto add_vertex = [&g](int id, std::string name, int capacity = -1) {
    auto vd = boost::add_vertex(g);
    g[vd] = { id, std::make_unique<custom_node>(name, capacity) };
    return vd;
    };

    add_vertex(0, "inner", 2);
    add_vertex(1, "outer", 3);
    add_vertex(2, "other");

  • 以上所有选项 Live On Coliru
    无论如何,如果您要问我,后者的界面要好得多。
    如果需要,可以使用ADL将其提供给其他人:
    Live On Coliru
    #include <boost/graph/adjacency_list.hpp>
    #include <fstream>
    #include <iostream>
    #include <iomanip>
    #include <memory>

    namespace MyLib { // for ADL demo
    struct custom_node {
    custom_node(std::string name, int capacity)
    : name(std::move(name)), capacity(capacity) {}

    std::string name = "uninitialized";
    int capacity = -1;

    friend std::ostream& operator<<(std::ostream& os, custom_node const& cn) {
    return os << "{" << std::quoted(cn.name) << ", " << cn.capacity << "}";
    }
    };

    struct VertexProperties {
    int id{};
    std::unique_ptr<custom_node> node;

    friend std::ostream& operator<<(std::ostream& os, VertexProperties const& vp) {
    os << vp.id;
    if (vp.node)
    os << ", " << *vp.node;
    return os;
    }
    };

    template <typename G>
    auto add_vertex(G& g, int id, const std::string& name, int capacity = -1) {
    auto vd = boost::add_vertex(g);
    g[vd] = { id, std::make_unique<custom_node>(name, capacity) };
    return vd;
    }
    }

    using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, MyLib::VertexProperties>;
    using custom_vertex = Graph::vertex_descriptor;
    using custom_edge = Graph::edge_descriptor;

    int main() {
    Graph g;

    add_vertex(g, 10, "inner", 2);
    add_vertex(g, 11, "outer", 3);
    add_vertex(g, 12, "other");

    for (auto vd : boost::make_iterator_range(vertices(g))) {
    std::cout << g[vd] << "\n";
    }
    }
    版画
    10, {"inner", 2}
    11, {"outer", 3}
    12, {"other", -1}
    有人提到设计吗?
    如果您想要的只是具有可选/惰性构造的唯一所有权,为什么不这样做:
    struct VertexProperties {
    int id{};
    std::optional<custom_node> node;
    };
    甚至只是
    struct VertexProperties {
    int id{};
    custom_node node;
    };
    所有权语义将是相同的,而没有成本:
    Graph g;

    add_vertex({10, custom_node{"inner", 2}}, g);
    add_vertex({11, custom_node{"outer", 3}}, g);
    add_vertex({12, custom_node{"other"}}, g);
    那只是使用BGL的标准 boost::add_vertex重载。没有 optional<>,它甚至可以变得更加简单:
    add_vertex({10, {"inner", 2}}, g);
    add_vertex({11, {"outer", 3}}, g);
    add_vertex({12, {"other"}}, g);
    也是 Live On Coliru (不带std::optional: Live)
    #include <boost/graph/adjacency_list.hpp>
    #include <fstream>
    #include <iostream>
    #include <iomanip>
    #include <memory>
    #include <optional>

    struct custom_node {
    custom_node(std::string name, int capacity = -1)
    : name(std::move(name)), capacity(capacity) {}

    std::string name = "uninitialized";
    int capacity = -1;

    friend std::ostream& operator<<(std::ostream& os, custom_node const& cn) {
    return os << "{" << std::quoted(cn.name) << ", " << cn.capacity << "}";
    }
    };

    struct VertexProperties {
    int id{};
    std::optional<custom_node> node;

    friend std::ostream& operator<<(std::ostream& os, VertexProperties const& vp) {
    os << vp.id;
    if (vp.node) os << ", " << *vp.node;
    return os;
    }
    };

    using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexProperties>;
    using custom_vertex = Graph::vertex_descriptor;
    using custom_edge = Graph::edge_descriptor;

    int main() {
    Graph g;

    add_vertex({10, custom_node{"inner", 2}}, g);
    add_vertex({11, custom_node{"outer", 3}}, g);
    add_vertex({12, custom_node{"other"}}, g);

    for (auto vd : boost::make_iterator_range(vertices(g))) {
    std::cout << g[vd] << "\n";
    }
    }
    版画
    10, {"inner", 2}
    11, {"outer", 3}
    12, {"other", -1}

    关于c++ - 使用std::unique_ptr boost 图形捆绑属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62532431/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com