C++ Boost

Boost Property Map Library

The Boost Property Map Library specifies concepts that define an interface for mapping key objects to value objects. Algorithms can take property maps as arguments relying on the concept definition and be ignorant of the underlying data structures. The algorithms can therefore be more generic. The property map concepts offer get() and put() functions that are used as if they are global functions; i.e, without a namespace qualifier. Furthermore, they can offer operator[] to access value objects.

Besides concepts, the Boost Property Map Library also contains property map types that provide property map interfaces for commonly used data structures, such as arrays, iterators, and associative maps.

Property maps are statically-typed; you can use the dynamic_properties class to access a set of property maps through a dynamically-typed interface (e.g., when you read an unknown set of attributes from a file).

Example

The following example from shows the property map functions in use. The templated fix_squares function has a property map as parameter.

#include <iostream>
#include <boost/property_map/property_map.hpp>

template <typename T> void fix_squares(T squares) // assuming that T is a property map
{
  typedef typename boost::property_traits<T>::value_type value_type; 
  
  value_type answer1 = get(squares, 1);    // <- use get() to get a value
  value_type& answer2 = squares[2];        // <- use operator[] to get a reference  
  //value_type& answer2 = get(squares, 2); // <- this would work too  

  bool all_correct = true;
  if(answer1 != 1) {
    all_correct = false;
    put(squares, 1, 1);                    // <- use put() to set a value
  }
  
  if( answer2 != 4) {
    all_correct = false; 	 
    answer2 = 4;                           // <- answer2 is a reference, hence this works
    // squares[2] = 4;                     // <- this would work too
    // get(squares, 2) = 4;                // <- this would work too
  }

  std::cout << all_correct ? "yes, all correct" : "no, something was wrong" << std::endl;

}

The following example creates a vector_property_map, and passes it to the fix_squares function twice:

int main()
{
  boost::vector_property_map<int> squares;
 
  squares[1] = 2;
  squares[2] = 4;
  
  fix_squares(squares); // first time to verify and fix mistakes
  fix_squares(squares); // second time to verify that all mistakes are fixed
  
  return EXIT_SUCCESS;
}

This example creates an associative_property_map instead, and passes it to the fix_squares function too:

#include <map>

int main()
{
  std::map<int, int> squares;
  boost::associative_property_map< std::map<int, int> > squares_adapted(squares);

  squares[1] = 1;
  squares[2] = 3;

  fix_squares(squares_adapted); // first time to verify and fix mistakes
  fix_squares(squares_adapted); // second time to verify that all mistakes are fixed
 
  return EXIT_SUCCESS;
}

Property Map Concepts

To differentiate between different forms of access, there are four property map concepts. The following table gives an overview of the property map concepts and the forms of access that they must offer:

  Readable.. Writable.. ReadWrite.. Lvalue.. Mutable..
value_type v = get(pmap, key);

X

 

X

X

X

value_type& v = get(pmap, key);      

X

value_type& v = pmap[key];  

X

const value_type& v = get(pmap, key);

X

X

const value_type& v = pmap[key];

X

X

put(pmap, key, value);

X

X

X

Where pmap is a property map object, key is a key_type object and value is a value_type object; all parameters are passed as const reference; and the following abbreviations are used to indicate property map concepts:

Abbrevation Full concept name Further details
Readable.. ReadablePropertyMapConcept readable property map concept
Writable.. WriteablePropertyMapConcept writable property map concept
ReadWrite.. ReadWritePropertyMapConcept read- and writable property map concept
LValue.. LvaluePropertyMapConcept lvalue property map concepts
Mutable.. Mutable_LvaluePropertyMapConcept lvalue property map concepts

Each property map object has a set of valid keys for which the mapping to value objects is defined; invalid keys result in undefined behaviour. The property map concepts do not specify the set of valid keys. A function that uses a property map should specify the expected set of valid keys in its preconditions.

Property Map Traits

There is a boost::property_traits class that can be used to deduce the types associated with a property map type. The following table gives an overview and the requirements on the trait types:
  Purpose Restrictions

boost::property_traits<PMap>::value_type

the value type of the map

any type

boost::property_traits<PMap>::key_type

the key type of the map

any type

boost::property_traits<PMap>::category

the tag for the type of access by the map. See the next section for definitions of category tags.

Concept... requires type convertible to:
Readable.. readable_property_map_tag
Writable.. writable_property_map_tag
ReadWrite.. read_write_property_map_tag
LValue.. lvalue_property_map_tag
Mutable.. lvalue_property_map_tag
boost::property_traits<PMap>::reference
the return type of get() and operator[]
Concept... requires
Readable.. assignable to value_type
Writable.. does not require this trait
ReadWrite.. assignable to value_type
LValue.. const value_type& or value_type&
Mutable.. value_type&

Note:There is no separate property tag for Mutable_LvaluePropertyMapConcept. And, even though lvalue_property_map_tag is convertible to writable_property_map_tag it does not necessarily indicate that a map of this category complies to WriteablePropertyMapConcept.

Property Map Category Tags

There is a tag struct for each of the categories of property maps, which is defined in the header <boost/property_map/property_map.hpp>.

namespace boost {

  struct readable_property_map_tag { };

  struct writable_property_map_tag { };

  struct read_write_property_map_tag :
    public readable_property_map_tag,
    public writable_property_map_tag { };

  struct lvalue_property_map_tag : 
    public read_write_property_map_tag { };

}

Property Map Types

The property map library provides several specific property map types that are listed in the table below. Furthermore, the header <boost/property_map/property_map.hpp> for pointers and provides the boost::property_trait andget() and put() functions for built-in C++ pointers, which means that T* is a model of Mutable_LvaluePropertyMapConcept, with key type std::ptrdiff_t.

Property map Summary
identity_property_map returns a copy of the key as value.
iterator_property_map converts any random access iterator into a lvalue property map
vector_property_map keeps its data in a dynamically resized vector
shared_array_property_map keeps its data in a fixed-size boost::shared_array
associative_property_map wraps around a Pair Associative Container or Unique Associative Container such as std::map
const_associative_property_map as above but non-mutable
ref_property_map wraps a reference to one particular object, and returns that reference whenever a key object is input.

History

The property map interface originated as data accessors in Dietmar Kühl's Masters Thesis on generic graph algorithms. The property map idea also appeared under the guise of decorators in early versions of the Generic Graph Component Library (GGCL), which is now the Boost Graph Library (BGL). The main motivation for the property map interface was to support the access of data associated with vertices and edges in a graph, though the applicability of property maps goes beyond this.

Acknowledgments

Thanks go to Dietmar Kühl for coming up with this mechanism, and thanks go to the Boost members who helped refine and improve the property map interface. Thanks to Dave Abrahams for managing the formal review of the BGL which included the property map library.

Notes to Implementors

Copying a property map should be inexpensive, since they are often passed by value.

Copyright © 2000-2002 Jeremy Siek, Indiana University (jsiek@osl.iu.edu)
Copyright © 2012 Alex Hagen-Zanker