]> git.lyx.org Git - lyx.git/blob - src/support/Changer.h
Amend 9b1dc338b2. Fix compilation in GCC 4.9
[lyx.git] / src / support / Changer.h
1 // -*- C++ -*-
2 /**
3  * \file Changer.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Guillaume Munch
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #ifndef LYX_CHANGER_H
13 #define LYX_CHANGER_H
14
15 #include "support/unique_ptr.h"
16
17
18 namespace lyx {
19
20 struct Revertible {
21         virtual ~Revertible() = default;
22 };
23
24 using Changer = unique_ptr<Revertible>;
25
26
27 /// A RefChanger records the current value of \param ref, allowing to
28 /// temporarily assign new values to it.  The original value is restored
29 /// automatically when the object is destroyed, unless it is disabled.
30 ///
31 /// RefChanger is movable, and doing so prolongs the duration of the temporary
32 /// assignment. This allows classes to supply their own changer methods.
33 ///
34 /// Naturally, be careful not to extend the life of a RefChanger beyond that of
35 /// the reference it modifies. The RefChanger can be disabled by calling
36 /// ->keep() or ->revert(). Once disabled, the reference is never accessed
37 /// again.
38 template<typename X>
39 class RevertibleRef : public Revertible {
40 public:
41         RevertibleRef(X & ref) : ref(ref), old(ref), enabled(true) {}
42         //
43         ~RevertibleRef() override { revert(); }
44         //
45         void revert() { if (enabled) { enabled = false; ref = old; } }
46         //
47         void keep() { enabled = false; }
48         //
49         X & ref;
50         X const old;
51 private:
52         bool enabled;
53 };
54
55
56 template <typename X>
57 using RefChanger = unique_ptr<RevertibleRef<X>>;
58
59
60 /// Saves the value of \param ref in a movable object
61 template <typename X>
62 inline RefChanger<X> make_save(X & ref)
63 {
64         return make_unique<RevertibleRef<X>>(ref);
65 }
66
67 inline Changer noChange()
68 {
69         return Changer();
70 }
71
72 /// Temporarily assign value val to reference ref.
73 /// To apply the change conditionally, one can write:
74 ///     Changer dummy = (cond) ? changeVar(ref, val) : noChange();
75 template <typename X>
76 inline RefChanger<X> changeVar(X & ref, X const val)
77 {
78         auto rc = make_save(ref);
79         ref = val;
80         return rc;
81 }
82
83 } // namespace lyx
84
85
86 #endif //LYX_CHANGER_H