You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用std::reference_wrapper绑定属性为Boost图添加边编译失败

Boost邻接表添加边触发顶点属性默认构造错误

问题背景

定义了带有自定义顶点属性的Boost邻接表:

using KinematicGraph =
    boost::adjacency_list<boost::vecS,
                          boost::vecS,
                          boost::bidirectionalS,
                          Model::SimulationObjects::map<std::reference_wrapper>::as<std::variant>>;

尝试通过add_edge添加边:

auto from = reinterpret_cast<const void *>(std::addressof(mapping.from()));
auto to = reinterpret_cast<const void *>(std::addressof(mapping.to()));

boost::add_edge(vertexMap[from], vertexMap[to], m_simulationObjectsGraph);

其中vertexMap是std::unordered_map<const void *, KinematicGraph::vertex_descriptor>,用于记录已添加顶点的描述符。

编译错误

[build] In file included from /home/dev/.conan2/p/b/boosta593711c2d7a0/p/include/boost/graph/adjacency_list.hpp:255:
[build] /home/dev/.conan2/p/b/boosta593711c2d7a0/p/include/boost/graph/detail/adjacency_list.hpp:2453:17: error: call to implicitly-deleted default constructor of 'std::variant<std::reference_wrapper<mandos::SimulationObject<mandos::Particle3DTag>>>'
[build]  2453 |                 bidir_rand_stored_vertex() {}

移除add_edge代码后编译正常,但不清楚为何会触发顶点属性的默认构造——明明没有主动创建新顶点。

原因分析

问题出在vecS顶点容器的行为上:

  • 当使用vecS作为顶点存储容器时,顶点描述符是整数类型(从0开始递增)。
  • 若调用add_edge时传入的顶点描述符大于等于当前图的顶点数量,Boost会自动创建所有缺失的顶点以补全到该描述符对应的索引。
  • 你的顶点属性是包含std::reference_wrapper的std::variant,而std::reference_wrapper没有默认构造函数,导致整个variant类型也无法默认构造,因此编译报错。

解决方案

方案1:确保顶点描述符有效

严格保证vertexMap中存储的所有顶点描述符,都是已经通过add_vertex显式添加到图中的有效描述符,避免出现描述符超出当前顶点数的情况。

方案2:更换顶点容器类型

将顶点容器从vecS改为listS(或其他非连续存储的容器):

using KinematicGraph =
    boost::adjacency_list<boost::vecS,
                          boost::listS,  // 更换为listS
                          boost::bidirectionalS,
                          Model::SimulationObjects::map<std::reference_wrapper>::as<std::variant>>;

listS的顶点描述符不是整数索引,无法自动创建顶点,必须显式调用add_vertex添加后才能使用,从根源避免自动创建顶点触发默认构造的问题。

方案3:调整顶点属性类型

修改顶点属性的variant类型,使其支持默认构造。例如给variant添加一个可默认构造的备选类型(如std::monostate):

// 假设可以调整map的模板参数,添加std::monostate
Model::SimulationObjects::map<std::reference_wrapper, std::monostate>::as<std::variant>

这样variant可以默认构造为std::monostate,满足Boost内部的构造需求。

内容的提问来源于stack exchange,提问作者jjcasmar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:52:34