Boost logo

Boost :

From: vesa_karvonen (vesa_karvonen_at_[hidden])
Date: 2002-02-12 02:15:23


--- In boost_at_y..., "bill_kempf" <williamkempf_at_h...> wrote:
[...]
>No, DBC does require language support. DBC relies on inheritance of
>the pre- and post-conditions as well as the invariants, and such
>inheritance requires language support. I've seen a few attempts
>at "grafting" this into C++ through the use of an intelligent
>preprocessor, but that is fragile and frankly still a form of
>language support.

I would prefer to have stronger metaprogramming support that would
allow the implementation of DBC and many other things.

Meanwhile, I've used a number of techniques for DBC. Consider the
following example:

  struct interface {
    // requires: pre(param)
    // ensures: post(method(param))
    virtual return_type method(param_type param) = 0;
    // ...
  };

  struct implementation_a : interface {
    return_type method(param_type param) {
      pre(param);
      // ...
      post(result);
      return result;
    }
    // ...
  };

  struct implementation_b : interface {
    return_type method(param_type param) {
      pre(param);
      // ...
      post(result);
      return result;
    }
    // ...
  };

The above is how interface contracts are typically found in C++
programs: they are described in the comments of the interface and
repeated for each implementation of the interface.

A much better alternative is to implement a contract decorator or
layer for each interface:

  struct interface_contract_decorator : interface {
    interface_contract_decorator(interface* implementation)
      : m_implementation(implementation) {}

    return_type method(param_type param) {
      pre(param);
      return post(m_implementation->method(param));
    }
    // ...
  };

  // or

  template<class implementation>
  struct interface_contract_layer : implementation {
    // A suitable constructor template

    return_type method(param_type param) {
      pre(param);
      return post(implementation::method(param));
    }
    // ...
  };

We can now easily add the contract to any implementation:

  return new interface_contract_layer<implementation_a>();

  // or

  return new interface_contract_decorator(new implementation_b());

These techniques have been very useful on many occasions.

When inheritance of the contracts is needed, which in my experience
isn't nearly as often as one would think, these techniques can be
adapted so that the desired effect is achieved.


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