我最近读过有关按 Contract 设计的内容,我想通过项目尝试使用它 . 当我尝试自己想出一些简单的解决方案时,我想到的第一件事就是这个:

#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;
}

它基本上使用隐式转换(构造函数)来启动负责检查 Contract 的包装器和显式转换操作符来返回它 . 我认为它会很好用 - 参数会被自动包装和检查,而内部函数会自动解包内容 . 与返回参数类似 . 我喜欢这个想法,因为合约将在一个地方定义和检查(参数/返回值),方法体将没有额外的行 .

但后来我对所有会发生的问题 - 我很可能不得不重载=运算符和可能的移动运算符,代码本身将非常灵活(每个 Contract 都必须有自己独立的实现而我是不确定模板会有帮助),更不用说构造函数中的 Contract 失败问题(我应该如何处理它?不检查其中的任何 Contract 或当场终止程序?) .

我查了一些关于它的文章:

  • this one虽然我的if-not-throw-exception当前使用的可能会更好依赖于宏,而且我喜欢这样做,'m not sure that I' d喜欢这样做,

  • this approach看起来稍微好些但是从2005年开始,所以一些更好的方法可能会在此期间出现,

  • 终于that one看起来像第一个更复杂的版本,并在有关DbC的其他问题上被提及 .

您是否知道任何方法/库可以产生干净,可读的代码,在定义每个新 Contract 时不需要额外的大量工作?一些稳定和成熟的东西,最好在Debian 7.3上已经可用,而不需要编译大量的外部库,也不需要添加几个新的存储库/ pinnings?

或者,您是否认为我最初提出的方法可以修复到实际有用的地步?

编辑

使这个问题不是一个偏离主题的问题: 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?