Search code examples
c++macros

How to Create a Macro That Declares a Variable, Declares a Variable for Its Previous Value, and Copies Variable to Previous Value?


I am writing a class that contains a lot of boolean variables. There is a lot of stuff like this:

bool var;
bool prev_var;
// more vars

void remember_stuff() {
    prev_var = var;
    // repeat for all vars
}

I'm hoping I can write a macro that allows me to do something like this:

DECLARE_BOOL(var1)
DECLARE_BOOL(var2)

and the preprocessor converts that into:

bool var1;
bool prev_var1;
bool var2;
bool prev_var2;

void remember_stuff() {
    prev_var1 = var1;
    prev_var2 = var2;
};

Is that possible?


Solution

  • It's not really possible to use marcos the way that you require.
    But even if there was some magic that allows that - using marcos is very rarely the best approach.

    Intsead you can encapsulate a single boolean parameter (with current and previous values) in a class/struct (BoolParam below), and store instances of that type in some container in your main class (MyBoolParams below).

    This is demonstrated below:

    #include <map>
    #include <string>
    #include <optional>
    
    // A single boolean parameter:
    struct BoolParam {
        bool m_val;
        std::optional<bool> m_prev_val;  // use `std::optional` to support a "not set" state in case it is needed
    
        BoolParam() {
            m_val = false;  // determine some default value
        }
    
        BoolParam(bool val) {
            m_val = val;
        }
    
        void remember() {
            m_prev_val = m_val;
        }
    
        // ... add more methods as needed
    };
    
    // Your main parameters container:
    struct MyBoolParams {
        std::map < std::string, BoolParam> m_vars;
    
        void set_param(std::string const& name, bool val) {
            m_vars[name] = BoolParam{ val };
        }
    
        void remember_stuff() {
            for (auto & [key, val] : m_vars) {
                val.remember();
            }
        }
    
        // ... add more methods as needed
    };
    
    int main() {
        MyBoolParams myBoolParams;
        myBoolParams.set_param("v1", true);
        myBoolParams.set_param("v2", false);
        myBoolParams.remember_stuff();
    }
    

    Live demo

    Notes:

    1. I used structs with all members public for simplicity.
    2. I used std::optional for m_prev_val to be able to determine if prev value has been set. If this is not needed you can use a plain bool.
    3. You can replace std::map with a simpler container line std::vector if you don't need the associativity by name.