Search code examples
c++static-assert

C++ Compile time check if a function called before another one


Lets say I have a class with two member functions.

class Dummy {
 public:
  void procedure_1();
  void procedure_2();
};

At compile time, I want to be sure that, procedure_1 is called before procedure_2. What is the correct way do implement this?


Solution

  • Maybe you could do it with a proxy-class. The idea is, that procedure_2 can't be accessed directly from outside (for example by making it private). procedure_1 would return some kind of proxy that allows the access to procedure_2.

    Some code below, allthough I don't consider it clean or safe. And if you want, you can still break the system.

    IMO such requirements should be handled without explicit validation, because it's quite cumbersome and impossible to make it absolutely safe. Instead, the dependency should be well documented, which also seems idiomatic in C++. You get a warning that bad things might happen if a function is used incorrectly, but nothing prevents you from shooting your own leg.

    class Dummy {
    private:
        void procedure_2() { }
    
        class DummyProxy
        {
            private:
                Dummy *parent; // Maybe use something safer here
            
            public:
                DummyProxy(Dummy *parent): parent(parent) {}
                
                void procedure_2() { this->parent->procedure_2(); }
        };
        
    public:
        [[nodiscard]] DummyProxy procedure_1() {
            return DummyProxy{this};  
        }  
    };
    
    int main()
    {    
        Dummy d;
        // d.procedure_2(); error: private within this context
        
        auto proxy = d.procedure_1();  // You need to get the proxy first
        proxy.procedure_2();           // Then 
    
        // But you can still break the system:  
        Dummy d2;
        decltype(d2.procedure_1()) x(&d2); // only decltype, function is not actually called
        d2.procedure_2(); // ooops, procedure_1 wasn't called for d2
    }