/* scoped_restore, a simple class for saving and restoring a value Copyright (C) 2016-2024 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef GDBSUPPORT_SCOPED_RESTORE_H #define GDBSUPPORT_SCOPED_RESTORE_H /* Base class for scoped_restore_tmpl. */ class scoped_restore_base { public: /* This informs the (scoped_restore_tmpl) dtor that you no longer want the original value restored. */ void release () const { m_saved_var = NULL; } protected: scoped_restore_base (void *saved_var) : m_saved_var (saved_var) {} /* The type-erased saved variable. This is here so that clients can call release() on a "scoped_restore" local, which is a typedef to a scoped_restore_base. See below. */ mutable void *m_saved_var; }; /* A convenience typedef. Users of make_scoped_restore declare the local RAII object as having this type. */ typedef const scoped_restore_base &scoped_restore; /* An RAII-based object that saves a variable's value, and then restores it again when this object is destroyed. */ template class scoped_restore_tmpl : public scoped_restore_base { public: /* Create a new scoped_restore object that saves the current value of *VAR. *VAR will be restored when this scoped_restore object is destroyed. */ scoped_restore_tmpl (T *var) : scoped_restore_base (var), m_saved_value (*var) { } /* Create a new scoped_restore object that saves the current value of *VAR, and sets *VAR to VALUE. *VAR will be restored when this scoped_restore object is destroyed. This is templated on T2 to allow passing VALUEs of types convertible to T. E.g.: T='base'; T2='derived'. */ template scoped_restore_tmpl (T *var, T2 value) : scoped_restore_base (var), m_saved_value (*var) { *var = value; } scoped_restore_tmpl (const scoped_restore_tmpl &other) : scoped_restore_base {other.m_saved_var}, m_saved_value (other.m_saved_value) { other.m_saved_var = NULL; } ~scoped_restore_tmpl () { if (saved_var () != NULL) *saved_var () = m_saved_value; } private: /* Return a pointer to the saved variable with its type restored. */ T *saved_var () { return static_cast (m_saved_var); } /* No need for this. It is intentionally not defined anywhere. */ scoped_restore_tmpl &operator= (const scoped_restore_tmpl &); /* The saved value. */ const T m_saved_value; }; /* Make a scoped_restore. This is useful because it lets template argument deduction work. */ template scoped_restore_tmpl make_scoped_restore (T *var) { return scoped_restore_tmpl (var); } /* Make a scoped_restore. This is useful because it lets template argument deduction work. */ template scoped_restore_tmpl make_scoped_restore (T *var, T2 value) { return scoped_restore_tmpl (var, value); } #endif /* GDBSUPPORT_SCOPED_RESTORE_H */