Вопрос № 0: я полагаю, что нет способа объявить неназванную локальную переменную? :)
Обычно вы можете набрать что-нибудь, используя макросы и __LINE__
, но если вы просто выберете достаточно странное имя, это должно быть уже сделано, поскольку у вас не должно быть более одного (напрямую) в одной области видимости. Это
class invariants_checker {};
template<class T>
class invariants_checker_impl : public invariants_checker {
public:
invariants_checker_impl(T* that) : that_(that) {that_->check_invariants();}
~invariants_checker_impl() {that_->check_invariants();}
private:
T* that_;
};
template<class T>
inline invariants_checker_impl<T> get_invariant_checker(T* that)
{return invariants_checker_impl<T>(that);}
#define CHECK_INVARIANTS const invariants_checker&
my_fancy_invariants_checker_object_ = get_invariant_checker(this)
у меня работает.
Вопрос # 1: допустимо ли передавать this
в конструктор invariants_checker
, который немедленно вызывает check_invariants
через этот указатель, даже если объект Foo
все еще находится в разработке?
Я не уверен, вызывает ли он UB технический. На практике это, безусловно, было бы безопасно, если бы не тот факт, что на практике член класса, который должен быть объявлен на определенной позиции по отношению к другим членам класса, рано или поздно станет проблемой.
Вопрос № 2: Видите ли вы другие проблемы с этим подходом? Вы можете улучшить это?
См. № 2. Возьмите класс среднего размера, добавьте полдесятилетия расширения и исправления ошибок двумя дюжинами разработчиков, и я думаю, что шансы испортить это хотя бы раз примерно на 98%.
Вы можете несколько смягчить это, добавив кричащий комментарий к элементу данных. Еще.
Вопрос № 3: этот подход новый или хорошо известный? Есть ли лучшие решения?
Я не видел такого подхода, но, учитывая ваше описание before()
и after()
, я сразу подумал о том же решении.
Я думаю, что у Страуструпа была статья (~ 15?) Лет назад, где он описал перегрузку класса дескриптора operator->()
для возврата прокси. Затем он может в своих ctor и dtor выполнять действия до и после, не обращая внимания на методы, вызываемые через него.
Редактировать: Я вижу, что Фрерих добавил ответ, уточняющий это . Конечно, если ваш класс уже не должен использоваться через такой дескриптор, это бремя для пользователей вашего класса. (IOW: это не сработает.)