0

My objective

I want to include property maps in a binary tree class, so I can access the graph vertices and write this syntax in the spirit of the BGL:

  using vertex_properties = std::string;
  using tree_type = binary_tree<vertex_properties, boost::no_property>;
  using vertex_descriptor = tree_type::vertex_descriptor;
  tree_type tree;
  vertex_descriptor a = add_vertex(tree, "a");
  vertex_descriptor b = add_vertex(tree, "b");
  assert(tree[a] == "a");
  tree[a] = tree[b];
  assert(tree[a] == "b");

My problem

I got the the add_vertex function working but I struggle enabling the bracket operator syntax.

What I tried

In the tree_type class I defined as a member an instance of the VertexManager class:

        template<typename Graph, typename VertexProperty>
        struct VertexManager
        {
            using vertex_descriptor = typename Graph::vertex_descriptor;
            using vertex_hashmap_type = std::map<vertex_descriptor, VertexProperty>;
            vertex_hashmap_type _vertex_property_hashmap;
            boost::associative_property_map< vertex_hashmap_type > _vertex_property_map { _vertex_property_hashmap };

            template<typename... Args>
            vertex_descriptor add_vertex_to_manager(Graph &g, Args&&... args)
            {
                vertex_descriptor key = add_vertex(g);
                VertexProperty value = { std::forward<Args>(args)...};
                put(_vertex_property_map, key, value);
                return key;
            }

            const VertexProperty& operator [](vertex_descriptor v) const
            {
                return get(_vertex_property_hashmap, v);
            }

            VertexProperty & operator [](vertex_descriptor v)
            {
                return get(_vertex_property_hashmap, v);
            }
        };

But it does not work, as the boost get function is defined with a const interface as follow:

  template <class T>
  inline const T& get(const T* pa, std::ptrdiff_t k) { return pa[k]; }

Is there a way to get a reference to an in-place element in the map?

WaterFox
  • 850
  • 6
  • 18
  • 1
    Uff I just realized the `boost::associative_pproperty_map` has an `operator[ ]` that does exactly what I want. I thought the interface was only `get` and `put` :/ oopsie – WaterFox Mar 21 '23 at 00:49
  • 1
    consider posting your self-answer – sehe Mar 21 '23 at 10:40

1 Answers1

0

I ended up looking in the implementation of the associative_property_map: it implements the required value_type& operator[const key_type& k]. Although it's not very clear why this operator is marked as const:

  template <typename UniquePairAssociativeContainer>
  class associative_property_map
    : public boost::put_get_helper<
       typename UniquePairAssociativeContainer::value_type::second_type&,
       associative_property_map<UniquePairAssociativeContainer> >
  {
    typedef UniquePairAssociativeContainer C;
  public:
    typedef typename C::key_type key_type;
    typedef typename C::value_type::second_type value_type;
    typedef value_type& reference;
    typedef lvalue_property_map_tag category;
    associative_property_map() : m_c(0) { }
    associative_property_map(C& c) : m_c(&c) { }
    reference operator[](const key_type& k) const {
      return (*m_c)[k];
    }
  private:
    C* m_c;
  };
WaterFox
  • 850
  • 6
  • 18