Boost logo

Boost Users :

From: Daryle Walker (darylew_at_[hidden])
Date: 2008-07-20 19:34:29


On Jul 20, 2008, at 9:21 AM, Zeljko Vrba wrote:

> And the basic question remains unanswered for me: How does MPL (or
> fusion for
> that matter) help in making more maintainable code? More
> maintainable as in:
>
> - less lines of code
> - code that is easier to understand
> - code that is easier to inspect at runtime with a debugger
> - code that can be modified by a C++ developer who does not know
> every dark
> corner of the template language
> - code that is written faster (i.e. takes less time to get a
> successful
> compilation) and works correctly the first time it is written
>
> How are fusion/MPL useful to an *application* programmer, not a
> library
> developer?

I'm not really into the whole MPL scene myself, but I'll give you
examples where I used it.

A while ago, Boost.Test added support for automatic unit tests. I
tried them out, and converted Boost.Rational to use them. The test
come in the form of a function you write with a special macro. A
similar macro was provided that made a function template instead, and
you supply a list of types to apply on that template for testing.
The list is in the form of a MPL list:

     typedef boost::mpl::list<short, int, long, MyInt>
rational_testing_list;

And I could apply the same tests for different versions of
boost::rational<T>.

Recently, I redid the integer-selection class templates to use
Boost.Test. Before this (like in Boost 1.35) that test
(integer_test.cpp) used a LOT of macros that assumed 32-bit values.
I wanted something more maintainable by the compiler proper. (For
instance, someone extended a macro for 64-bit support, although I
never supported that for any other code.) I decided to go with
automatic test templates and lists. The base list was like:

     typelist boost::mpl::vector<unsigned char, unsigned short,
unsigned, unsigned long, unsigned long long> unsigned_integer_list;

with some alterations:

     1. Use "__int64" instead of "long long" on Windows systems
     2. Exclude both if I'm not on a 64-bit system
     3. Exclude types that are strong-typedefs of a "smaller" type

(so "unsigned char" is the only type guaranteed) done by the
preprocessor. I use MPL to synthesize the data I actually needed for
the tests from this list.

     1. Create a list of corresponding signed types (help from
Boost.TypeTraits)
     2. Create a list of bit lengths used for each integral type,
using a custom meta-function I made with std::numeric_limits. This
means that I didn't not hard-code the {8, 16, 32, 64} values and the
tests will work on platforms without a 64-bit type, or even on old
systems that don't use the 8/16/32 system (like 36-bit ints with 9-
bit char).
     3. A list of all the median bit lengths between the values in
[2], so I can test lengths between the exact ones.
     4. A combined list of [2] and [3]
     5. [4] extended with a length beyond all valid bit lengths

In addition, I changed the implementation of the integer-selection
classes. Before they could give a compiler error if a given input
length was invalid. Now they're MPL-compatible and just lack a
member "type" if the input is invalid. (The old templates now call
these new ones and still cause a hard error.) Without this, tests
using [5] aren't possible. Said tests use SFINAE to make decisions.

(I think that MPL lists are limited to 20 elements total. So I made
list [3] to be selective. Otherwise, I could have carpet-bombed with
range_c<int, 0, 65> or such.)

All of these lists are compile-time, but based on a list I couldn't
hard-code. It would have been harder without MPL manipulations.

-- 
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT hotmail DOT com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net