Boost logo

Boost :

From: Vesa Karvonen (vesa.karvonen_at_[hidden])
Date: 2001-06-03 11:54:00


I'm currently writing metacode for my resource library that I hope to be
able to offer to Boost next week. I find that the Boost metaprogramming
and type traits facilities are not mature enough for my taste, so I have
ported a mini version of our metaprogramming facilities to Boost
conventions.

call_traits
===========

The call_traits<> is basically a mini-BLOB (antipattern). Specifically the
call_traits<> template is four functions in one. It is preferable to have
simple primitive template metafunctions, because:

1. Such metafunctions can be made to use standard interfaces rather than
the special case interface of call_traits.

2. Primitive metafunctions are easier to use, understand and port (fact of
life). For instance, should one little thing fail to compile in call
traits, you might not be able to port the whole thing.

3. Primitive metafunctions scale better in large scale development (with a
BLOB you need to include everything whether or not you need it). (In fact,
currently I only need param_type.)

So, I would prefer to see the special interface of call_traits<>:

  template <typename T>
  struct call_traits<T>
  {
     typedef ... value_type;
     typedef ... reference;
     typedef ... const_reference;
     typedef ... param_type;
  };

split into four distinct metafunctions (here in pseudo code):

  namespace call_traits
  {
    template<class T> struct value_type {typedef ... type;};
    template<class T> struct reference_type {typedef ... type;};
    template<class T> struct const_reference_type {typedef ... type;};
    template<class T> struct param_type {typedef ... type;};
  }

The above metafunctions are clearly superior to use in metacode than the
call_traits<> template. I can provide examples if you don't trust me.

arithmetic_traits
=================

The boost/arithmetic_traits.hpp can be simplified by a factor of ~4.
Currently the arithmetic types are repeated 4 times:
- as non-cv types,
- as const types,
- as volatile types, and
- as const volatile types.

A smarter implementation would look something like this:

    namespace detail
    {
      typedef
        make_typelist
        < const volatile char
        , const volatile signed char
        , const volatile unsigned char
        , const volatile short
        ,...
>::type const_volatile_arithmetic_types;

       template<class T>
       struct type_const_volatile
       { typedef const volatile T
           type;
       };

       template<class T>
       struct type_identity
       { typedef T
           type;
       };
    }

    template<class T>
    struct is_arithmetic
    {
     enum
     { value =
         typelist_has
         < detail::const_volatile_arithmetic_types
         , typename type_inner_if
           < is_reference<T>::value
           , detail::type_identity<T>
           , detail::type_const_volatile<T>
>::type
>::value;
      };
    };

MPL
===

Technical Issues in Boost MPL:
- The current code is not completely ported to MSVC++, so I can not use
it.
- The factory template uses O(N*N) tokens, which is not optimal. It is
possible to do with only O(N) tokens, which can significantly reduce
compilation times.
- The code makes no use of private or public to hide implementation
details or hilite the interfaces of metacode. This makes it more difficult
to understand the code.
- What is the purpose of the SequenceCategory and TraitsType template
parameters of list_node? I find that those complicate the implementation
significantly with little or no benefit over pure, cons based, proper
typelists. Can you give a concrete examples that would demonstrate the
superiority of the MPL technique?
- list_node<> doesn't check the validity of the template arguments. At
least NextNode has special requirements. This same problem can be seen in
many places.
- What is wrong with using enum {} when there is no particular reason to
have a specific type? Does it fail on some broken compilers? Is the use of
BOOST_STATIC_CONSTANT() always worth it? IIRC even Bjarne Stroustrup has
commented that static class constants are a misfeature.
- The endline layout is a bad idea. It makes maintanance more difficult. I
can already pinpoint examples of broken code layout in MPL. See Code
Complete, ISBN 1-55615-484-4, for details. IMO Boost should have a
guideline that says that library authors are recommend not to use endline
layout, because it is not maintainable.
- MPL should be separated into multiple more cohesive libraries. For
example:
  - type traits (is_same, is_convertible, ...)
    - actually Boost already has this library and I don't see much value
in duplicating the library.
  - template metaprogramming (if, switch, for, while, ...)
  - metadata-structures (lists, trees, etc...)
    - I think that a lot could be learned by using existing knowledge on
functional programming. For example:
      - Chris Okasaki: Purely Functional Data Structures, ISBN 0521663504


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk