c++boost-graphboost-property-map

Enabling bracket operator syntax with Boost Property maps?


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?


Solution

  • 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;
      };