Search code examples
c++11boolean-operations

How to get a reference to the negation of a bool?


For example, if I have a bool value v, I want a reference to !v that can change when v changes. An example use will be:

class A {
    bool& isOpen;
    A(bool& value): isOpen(value) {}
    void f() {
        if (isOpen) {
            doSomething();
        }
    }
};

class B {
    bool& isClosed;
    B(bool& value): isClosed(value) {}
    void g() {
        if (isClosed) {
            doSomething();
        }
    }
};

int main() {
    bool isOpen = true;
    A a(isOpen);
    B b(negattive_reference_of(isOpen));
    a.f(); // doSomething()
    b.g(); // do nothing
    isOpen = false;
    a.f(); // do nothing
    b.g(); // doSomething()
}

Is there anyway in C++ to acheive a similar effect?


Solution

  • Under the hood reference is equivalent to a constant pointer to some variable (compiler just gives you a syntax sugar of how to work with such pointers so that they are always initialized). So you wan't to have the same variable and two different pointers to it, one of which will dereference to true and the other to false. That is obviously impossible. The OOP -way to do it would be to pass not reference to boolean but some interface to your classes and use implementation that uses same boolean variable:

    class IIsOpenProvider
    {
    public:
        virtual ~IIsOpenProvider() = 0;
        virtual bool GetOpenValue() = 0;
    };
    
    class IIsClosedProvider
    {
    public:
        virtual ~IIsClosedProvider() = 0;
        virtual bool GetClosedValue() = 0;
    };
    
    class ValueProvider : public IIsOpenProvider, public IIsClosedProvider
    {
    public:
        bool GetOpenValue() override { return isOpen; }
        bool GetClosedValue() override { return !isOpen; }
    
    private:
        bool isOpen;
    };
    
    class A {
        IIsOpenProvider& isOpen;
        A(IIsOpenProvider& value): isOpen(value) {}
        void f() {
            if (isOpen.GetOpenValue()) {
                doSomething();
            }
        }
    };
    
    class B {
        IIsClosedProvider& isClosed;
        B(IIsClosedProvider& value): isClosed(value) {}
        void g() {
            if (IIsClosedProvider.GetClosedValue()) {
                doSomething();
            }
        }
    };
    
    // usage
    ValueProvider val;
    A a(val);
    B b(val);