Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Tutorial 4 - Multi-type Containers

There are two types of containers in the library that can hold objects of heterogeneous types. The type_map is designed for use with shared_library so that a standard function signature, taking a type_map, can be provided by each shared library, helping to avoid type safety problems.

The second type, parameter_map, is designed for use with reflections or factories where the type of the function is not known at compile time. A parameter_map can be passed into such a factory or reflection, and then searched for needed parameters, and return a list of missing parameters if necessary.

The type_map is the simplest of the two, as it can hold exactly one element of each type. It can hold multiple objects, but they will each be of a different type.

Here's an example showing a type_map holding an int and a std::map<std::string, std::string>.

using namespace boost::extensions;

// A type_map can hold one of each type, constructed
// as needed.
type_map types;
int& first_int(types.get());
first_int = 100;

// This actually points to the same int as first_int.
int& second_int(types.get());

second_int = 500;

// This will print out 500.
std::cout << "first_int: " << first_int << std::endl;

// Arbitrary default-constructible types can be held in a type_map.
std::map<std::string, std::string>& string_pairs(types.get());

Note that pulling an integer out of it twice results in two references to the same integer. The same occurs with any type placed into the type_map.

A parameter_map on the other hand, can hold any number of elements of any type, and can automatically convert objects to compatible types.

The basic type stored in a parameter_map is a parameter. It is possible to declare a parameter as being convertible to other types.

By default, a static_cast is used to convert the types, but any conversion function can be provided.

parameter<int>* p = new parameter<int>(5);
p->converts_to<float>();
p->converts_to<double>();

To have a float change to its ceiling when converted to an integer, one could write:

void FloatCeilingToInt(float* f, int* i) {
  *i = static_cast<int>(std::ceil(*f));
}

parameter<float>* p = new parameter<float>(4.9f);
p->converts_to_with_func(&FloatCeilingToInt);
p->cast<int>(); // returns 5

Once created, a parameter can be placed into a parameter_map, along with some sort of name. This name can be of arbitrary type: parameter_map is a specialized basic_parameter_map with the std::string type as the name, but other types are also possible.

A parameter_map works much like a std::multi_map - since it is built on one. It has a few specialty methods though. It is possible, for instance, to retrieve all values that match a certain type and name, or the first value that matches.

parameter_map map;
std::vector<generic_parameter<int>*> int_vector(map.get("some_int_name"));
generic_parameter<int>* first_int(map.get_first("some_int_name"));


PrevUpHomeNext