是否保证在随机访问下访问顶点的名称和边的权重是高效且快速的,如下所示:
是的。这些属性实际上是与顶点/边节点内联存储的。描述符实际上是指向该节点的类型擦除指针。如果您将属性存储想象成一种带有get<> 访问器的元组,name_map[*vi] 最终会内联到 get<N>(*static_cast<storage_node*>(vi)) 之类的东西。
我的部分困惑来自一般的 std::map 特性,它也不支持随机访问
属性映射不像 std::map;它们可能是连续的,它们可能是基于节点的、有序的、无序的,甚至是计算的。实际上 Boost Property Map 可能更接近某些函数式编程语言中的镜头概念。它是一组函数,可用于对给定键类型的(可变)投影进行建模。
另见:
好奇心胜...代码生成
让我们看看生成了什么代码:
Live On Compiler Explorer
#include <boost/graph/adjacency_list.hpp>
#include <fmt/format.h>
using G =
boost::adjacency_list<boost::listS, // out edges stored as list
boost::listS, // vertices stored as list
boost::directedS,
boost::property<boost::vertex_name_t, std::string>,
boost::property<boost::edge_weight_t, double>>;
using V = G::vertex_descriptor;
using E = G::edge_descriptor;
void test(V v, E e, G const& g) {
auto name = get(boost::vertex_name, g);
auto weight = get(boost::edge_weight, g);
fmt::print("{} {}\n", name[v], weight[e]);
}
int main()
{
G g;
E e = add_edge(add_vertex({"foo"}, g), add_vertex({"bar"}, g), {42}, g).first;
test(vertex(0, g), e, g);
}
打印
foo 42
但更有趣的是,codegen:
test(void*, boost::detail::edge_desc_impl<boost::directed_tag, void*>, boost::adjacency_list<boost::listS, boost::listS, boost::directedS, boost::property<boost::vertex_name_t, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::no_property>, boost::property<boost::edge_weight_t, double, boost::no_property>, boost::no_property, boost::listS> const&): # @test(void*, boost::detail::edge_desc_impl<boost::directed_tag, void*>, boost::adjacency_list<boost::listS, boost::listS, boost::directedS, boost::property<boost::vertex_name_t, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::no_property>, boost::property<boost::edge_weight_t, double, boost::no_property>, boost::no_property, boost::listS> const&)
sub rsp, 40
mov rax, qword ptr [rsp + 64]
movups xmm0, xmmword ptr [rdi + 24]
mov rax, qword ptr [rax]
movaps xmmword ptr [rsp], xmm0
mov qword ptr [rsp + 16], rax
mov rcx, rsp
mov edi, offset .L.str
mov esi, 6
mov edx, 173
call fmt::v7::vprint(fmt::v7::basic_string_view<char>, fmt::v7::format_args)
add rsp, 40
ret
你看,没有算法开销,只是取消引用。
¹ 实际上,属性存储在一种类似于 Lisp 的列表类型中,其最终行为类似于元组。 Boost Graph 比元组早了相当长的时间。我想如果你想要一个可以将它与 Boost Fusion 的 map 类型(也有一个类型键)进行比较。