home mail me! RSS (2.0) feed

Brief intro to Boost and TR1

Boost is a library of helping constructs for modern C++ development. What sets Boost apart from most other libraries is that it is infrastructural and horizontal in that it extends the vocabulary of the developer in any kind of problem solving, no matter what the domain.

This quite unique feature - along with the fact that some of the most prominent members of the Boost community also happen to be equally prominent members of the C++ Standard Committee… - has made Boost the foundation of the most radical library additions to the next version of C++, which we hope will be standardized by 2010.

Before the next standardized version of C++, we have a Technical Report, called TR1, which is basically the core of Boost library under the namespace std::tr1. This post will not use that namespace, but the regular Boost namespace(s), i.e., boost. In fact, that namespace is assumed to be included in the samples below.

NOTE 1: there are minor discrepancies between the Boost and TR1 APIs, in which case I will try to expose those differences.

NOTE 2: there are lot of interesting utilities in Boost which are not part of TR1, but they will be ignored in this post!

Boost philosophy

DISCLAIMER: this is not the official philosophy of Boost but just my (futile?) attempts at describing the essence of Boost.

Boost is based on Generic Programming which in some sense is an orthogonal “paradigm aspect”, which in C++’s case is weaved into the OOish fabrics. One can view Generic Programming as the Art of Implementing Design Patterns. I am fully aware that some Design Pattern proponents might cringe at this apparent oxymoron of implementing a pattern. Let me just humbly state that those proponents are wrong: Generic Programming is all about realizing patterns in the form of code, adorned with quite formal constraints.

In short, Generic Programming transcends the barriers of types and deals with Concepts and Models, where the former notion is a category specified by some more or less formal criteria and the latter a type adhering to those criteria.

For instance, one says that a type T is a Model of the CopyConstructible Concept if one can create a new T from an old one, or, more precisely, if the expression T(t) is valid and creates a new T being a “reasonable” copy of t, for t being of type T. Yes, one has to deal with “reasonability” and loose semantics added to strict syntactical requirements when defining Concepts.

Once having those Concepts, one can create generic code assuming Models for those Concepts. That is the process of Generic Programming.

Features

The order of these features are the same as in the following book:
The C++ Standard Library Extensions: A Tutorial and Reference

  • Tuples: template tuple and helper functions make_tuple and tie
  • Smart Pointers: templates shared_ptr and weak_ptr
  • Smart Arrays: template array
  • Hash Maps: template unordered_set, unordered_multiset, unordered_map and unordered_multimap and helper template hash
  • References: the ref and cref helper functions along with wrapper types
  • Functoid Adapters: better binder, bind and member function wrappers, mem_fn
  • Polymorphic Functoids: the template function
  • Type Traits: meta predicates such as is_integral, is_array and is_pointer, and meta mappers such as remove_reference and add_pointer
  • Random Numbers: engines such as linear_congruential or mt19937 and distributions such as normal_distribution and uniform_int
  • Regular Expressions: the regex and cmatch types, and the regex_search function

If I had to pick two features, it would be smart pointers and bind. Those are necessary in order to keep some kind of sanity when developing.

The individual features, with notes about what corresponding (or at least related) notions that are already in place in the C++ Standard and how TR1 differs from Boost, follow.

Tuples

Extends - and interoperates with - the pair construct in Standard C++.

To create, use constructor or the helper function (template) make_tuple.

To access, use get<index>() or tie.

NOTE: make_tuple creates a tuple of the proper (unreferenced) types of the parameters, so use ref or cref to conserve reference types.

Samples

  • make_tuple("Jagr", 108).get<0>() will create an instance of type tuple<string,int> and then get the first component of it, i.e., the string "Jagr"

Smart Pointers

There is only one smart pointer in Standard C++: auto_ptr.

This is a whole framework, involving:

  • shared_ptr that increments and decrements a reference counter to shared resources
  • weak_ptr that is a passive reference to a shared resource
  • shared_from_this which enable a method to treat this as a shared pointer
  • type casting, via static_pointer_cast and dynamic_pointer_cast

The reason for all these parts to coexist in a framework, instead of the more modular approach of providing “auxiliary” functionality on top of a shared_ptr core is that such external attempts would necessarily involve creating parallel “smart pools” for the same shared resource, which would eventually result in dangling references.

Samples

  • shared_ptr<Foo> myFoo(new Foo); will create a smart pointer referencing a new Foo instance.
  • weak_ptr weakFoo(myFoo); will create a reference that does not increment the reference counter

Smart Arrays

In C++, arrays are quite weak types, in that they decay into pointer types fairly easily, such as when using the name of an array variable in anything but sizeof.

Additionally, even though an array is conceptually a container, it is not a proper Standard C++ container (size, begin, end etc.)

These two problems are solved by the template array.

In TR1, the array also implements the tuple API, i.e., provides get<n>() and the meta functions to determine component type and array size.

Hash Maps

In TR1, they are called unordered associative containers.

Type Traits

A bunch of useful meta functions mapping a type to its traits.

  • unary predicates, such as is_pointer, is_polymorphic and has_trivial_constructor
  • binary predicates, such as is_same and is_convertible
  • type transformers, such as add_const and remove_reference

Functoid Adapters

This is the pearl of Boost, objectively speaking.

If you have fiddled around with the Standard bind1st for a while, you understand what I mean.

The helper function bind, with its hidden wrappers, support the a common and generic handling of everything callable, including partial currying (or close instantiations.)

Samples

  • bind(foo, _1, 42)(3) reduces to foo(3, 42)

Polymorphic Functoids

This enables the developer to store and pass around any functoid. There is a cost, and that is indirection via regular OOP runtime polymorphism using the pimpl pattern.

Samples

  • function<int (int)> myFun = bind(foo, _1, 3) where foo is a binary functoid

Random Numbers

This library separates the concerns (or Concepts, to use Generic Programming lingo) of creating the random values and distributing them. These concepts are called Random Engine and Random Distribution.

You connect these two concepts via the template variate_generator.

Samples

  • [taking from the Boost documentation]
    boost::mt19937 rng; // produces randomness out of thin air
    // see pseudo-random number generators
    boost::uniform_int<> six(1,6) // distribution that maps to 1..6
    // see random number distributions
    boost::variate_generator >
    die(rng, six); // glues randomness with mapping
    int x = die(); // simulate rolling a die

Regular Expressions

Regular expressions are represented by regex instances, and search then conducted with regex_search or regex_match.

There is also a sregex_token_iterator is an iterator type to use generic algorithms and functions with regular expressions.

Samples

  • regex_search("what is this", match, regex("is$"));
  • regex_match("what is this", regex("is$")) will evaluate to something truish.

Sorry for this quick and dirty overview of TR1. I will have reasons to come back with much more substantial information later. Till then, read the recommended book above, or this introduction to the Boost library (or, technically, “libraries”):
Beyond the C++ Standard Library: An Introduction to Boost

davber does IT » Scripting in Python, Ruby, Perl? No, in C++! said,

January 29, 2007 @ 9:48 pm

[…] This provides a perfect environment for understanding hairy semantic subtleties of C++ as well as learning all those nifty algorithm templates of the Standard Library. Such as realizing that there is no copy_if And, there is built-in support for the Boost Library, of which core parts will be part of the next version of the C++ standard. […]

RSS feed for comments on this post · TrackBack URI

Leave a Comment

You must be logged in to post a comment.