Boost logo

Boost :

From: Michael Kenniston (Msk_at_[hidden])
Date: 2001-07-13 14:47:03

In the design of the Quantity library, a trade-off
arose which might be of more general interest.
It affects the interface, not just the implementation,
so it's important to get it "right".

The general problem is the need for a bunch of constants
of type T, where T is a user-defined class. In the
specific case of the quantity library, T is
"quantity<...>" and the constants are things like
"foot" and "meter".

There are (at least) two ways of handling this:

    1 - const T mything( init_value );
        // ...
        T x = mything;

    2 - inline T mything() { return mything( init_value ); }
        // ...
        T x = mything();

If the constructor for T is simple enough, either of
the two methods should allow a good compiler to optimize
well by inlining the init_value, so efficiency does not
appear to be a major consideration here.

The first method is certainly more conventional, provides
a cleaner, more concise syntax without the extraneous "()",
and so is probably a little easier to understand and to use.
It also clearly expresses the "const" nature of mything.

However, it also introduces the problem of guaranteeing
correct initialization of static variables before they
are used. There are certainly documented techniques in
the literature to guarantee initialization before use, but
they are not without problems:

1) The efficiency requirement (access to mything must be
as fast as access to a double) prohibits some of the usual
techniques (e.g. a bool "initialized" flag).

2) The portability requirement (code must not rely on anything
implementation-dependent) makes me wary of anything very
subtle or sophisticated - even if my code is ISO-compliant,
the compiler might not be.

3) I want the library users to be able to define their own
constants, without burdening them with complex requirements
of a fancy initialization strategy.

The second method also makes it very hard to come up with
a work-around, that isn't really, really ugly, for the
conflict of keyword "pascal" with SI unit "pascal" .

For all of these reasons, I've tentatively chosen the second
approach (inline functions) for the library. Having that
extra "()" all over the place isn't the prettiest syntax,
but if you think of the inline routines as being sort of
like accessors then it's no worse than get() and put().
In return the code is simple, robust, and easy to understand.

I'd be interested in hearing your opinions: Does this seem
like a reasonable trade-off, or might I be overlooking
something here?

- Michael Kenniston

Boost list run by bdawes at, gregod at, cpdaniel at, john at