проверка инвариантов в C ++

Существуют ли какие-либо установленные шаблоны для проверки инвариантов классов в C ++?

В идеале, инварианты должны автоматически проверяться в начале и в конце каждой публичной функции-члена. Насколько мне известно, C с классами предоставлял специальные до и после функций-членов, но, к сожалению, разработка по контракту не была популярна в то время, и никто, кроме Бьярна, не использовал эту функцию. , поэтому он удалил его.

Конечно, вставка вручную вызовов check_invariants () в начало и конец каждой общедоступной функции-члена утомительна и подвержена ошибкам. Поскольку RAII является предпочтительным оружием для работы с исключениями, Я придумал следующую схему определения средства проверки инвариантности в качестве первой локальной переменной, и эта программа проверки инвариантности проверяет инварианты как во время создания, так и во время уничтожения:

template <typename T>
class invariants_checker
{
    const T* p;

public:

    invariants_checker(const T* p) : p(p)
    {
        p->check_invariants();
    }

    ~invariants_checker()
    {
        p->check_invariants();
    }
};

void Foo::bar()
{
    // class invariants checked by construction of _
    invariants_checker<Foo> _(this);

    // ... mutate the object

    // class invariants checked by destruction of _
}

Вопрос №0: Я полагаю, что нет способа объявить безымянный локальный переменная? :)

Нам все равно придется вызывать check_invariants () вручную в конце конструктора Foo и в начале деструктора Foo . Однако многие тела конструкторов и деструкторов пусты. В этом случае, можем ли мы использовать invariants_checker в качестве последнего члена?

#include <string>
#include <stdexcept>

class Foo
{
    std::string str;
    std::string::size_type cached_length;
    invariants_checker<Foo> _;

public:

    Foo(const std::string& str)
    : str(str), cached_length(str.length()), _(this) {}

    void check_invariants() const
    {
        if (str.length() != cached_length)
            throw std::logic_error("wrong cached length");
    }

    // ...
};

Вопрос № 1: Допустимо ли передавать this конструктору invariants_checker , который немедленно вызывает check_invariants через этот указатель, хотя объект Foo все еще находится в стадии разработки?

Вопрос № 2: Вы видите какие-либо другие проблемы с этим подходом? Можете ли вы его улучшить?

Вопрос № 3: Этот подход новый или хорошо известный? Есть ли более подходящие решения?

15
задан fredoverflow 19 January 2011 в 13:58
поделиться