Проектирование по контракту в C ++ с неявными конструкторами / операторами явного преобразования

Я недавно читал о дизайне по контракту, и я хотел бы попробовать его в проекте. Первое, что пришло мне в голову, когда я попытался найти какое-то простое решение самостоятельно, было это:

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

Он в основном использует неявное преобразование (конструктор) для инициации оболочки, ответственной за проверку контракта, и явный оператор преобразования для его возврата. Я думал, что это будет работать довольно хорошо — аргументы будут автоматически упакованы и проверены, а внутри функций это автоматически развернет содержимое. Аналогично с возвращаемыми аргументами. Мне нравится идея, так как контракт будет определен и проверен только в одном месте (аргумент / возвращаемое значение), а тело метода будет свободно от дополнительных строк.

Но затем я подумал обо всех тех проблемах, которые могли бы возникнуть — мне, скорее всего, пришлось бы перегружать = оператор и возможный оператор перемещения, сам код был бы не очень гибким (каждый контракт должен иметь свою собственную отдельную реализацию, и я не уверен, что шаблон поможет), не говоря уже о проблеме с провалом контракта внутри конструктора (как мне с ним работать? Не проверять контракт внутри него или не завершать программу на месте?).

Я проверил несколько статей об этом:

  • этот хотя может быть лучше, чем то, что в настоящее время используется моим if-not-throw-exception, зависит от макросов, и я не уверен, что хотел бы сделать это таким образом,
  • этот подход выглядит немного лучше, но это с 2005 года, так что какой-то лучший способ сделать это, возможно, придет в то же время,
  • в конце концов вон тот Похоже на более сложную версию первого, и был упомянут по другому вопросу, касающемуся DbC.

Знаете ли вы какой-либо подход / библиотеку, которая привела бы к чистому, читабельному коду, который не требует больших дополнительных усилий при определении каждого нового контракта? Что-то стабильное и зрелое, желательно уже доступное в Debian 7.3 без компиляции множества внешних библиотек или добавления нескольких новых репозиториев / закреплений?

В качестве альтернативы, вы думаете, что подход, который я придумал сначала, мог бы быть зафиксирован до такой степени, что он был бы действительно полезен?

РЕДАКТИРОВАТЬ

Чтобы этот вопрос не был не по теме: Было бы безопасно использовать классы, определенные аналогично определенным контрактам? Будут ли какие-то подводные камни, и, если таковые имеются, можно ли избежать того, как я буду использовать эти классы или как я их реализовал?

3

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]