Design by Contract in C++ with implicit constructors/explicit conversion operators

176 views Asked by At

I've recently read about Design by Contract and I'd like to try to us it in by project. First thing that came to my mind when I tried to came up with some simple solution on my own was this one:

#include <iostream>
using namespace std;

template <typename Type>
class Positive {
    Type value;

public:
    Positive(
        Type positive
    ) :
        value(positive)
    {
        if (!condition())
            errorAction();
    }

    Positive(
        const Positive& positive
    ) :
        value(positive.value)
        {} // no need to check since variable HAS to respect the contract

    Positive(
        const Positive&& positive
    ) :
        value(positive.value)
        {} // no need to check since variable HAS to respect the contract

    Positive& operator=(
        const Positive& positive
    ) {
        value = positive.value;
        return *this;
    }

    Positive& operator=(
        const Positive&& positive
    ) {
        value = positive.value;
        return *this;
    }

    operator Type() {
        return value;
    }

private:
    bool condition() {
        return value > 0;
    }

    void errorAction() {
        cout << "not positive value: " << value << endl;
        exit(-1);
    }
};

// contract: both inputs and output are positive
template <typename Type>
Positive<Type> minusPositive(
    Positive<Type> x,
    Positive<Type> y
) {
    return x - y;
}

int main() {
    int x = 10;
    int y = 20;
    int z = minusPositive<Type>(x, y);  // should fails since x-y <= 0

    cout << "Should never display this: " << z << endl;

    return 0;
}

It basically use implicit conversion (constructor) to initiate wrapper responsible for checking contract and explicit conversion operator to return it. I was thinking that it would work quite nice - arguments would be automatically wrapped and checked, and inside functions it would automatically unwrap content. Similarly with return arguments. I like the idea since contract would be defined and checked just in one place (argument/returned value) and the body of method would be free of additional lines.

But then I though about all those issues that would happen - I would most likely have to overload = operator and possible move operator, the code itself would'n be very flexible (each contract would have to have its own separate implementation and I'm not sure template would help), not to mention problem with failing contract inside a constructor (how should I deal with it? Not check any contract inside it or terminate program on the spot?).

I've checked some articles about it:

  • this one while might be better that currently used by my if-not-throw-exception relies on macros, and I'm not sure that I'd like to do it that way,
  • this approach looks slightly better but it's from 2005 so some better way of doing it might have come in the meantime,
  • finally that one looks like more sophisticated version of the first one, and was mentioned on other question concerning DbC.

Do you know any approach/library that would result in a clean, readable code, that doesn't require a lot of additional effort with defining each new contract? Something stable and mature, preferably already available on Debian 7.3 without compiling tons of external libraries nor adding several new repositories/pinnings?

Alternatively, do you think that the approach that I came up at first, could be fixed to the point where it would be actually useful?

EDIT

To make this question not an off-topic: would it be safe to use classes defined similarly to the define contracts? Would there be some pitfalls, and if there are, can there be avoided by the way I would use those classes or the way I implemented them?

0

There are 0 answers