22
class MyObj{
public:
    void myFunc(){
         //ToBeExecutedJustOnce
    }

};

I have a function that I want to be executable only once for the lifetime of MyObj. There may be many instances of MyObj, and each should be able to execute that function once. So if I have:

MyObj first;
MyObj second;
MyObj third:
first.myFunc(); // Should execute
second.myFunc(); // Should execute
third.myFunc(); // Should execute
first.myFunc(); // Should not execute
second.myFunc(); // Should not execute
third.myFunc(); // Should not execute

Options:

  1. member variable: If I use a member variable, then other functions within MyObj can access it and change it.
  2. global static variable: Can't work because first,second and third will all be checking the same variable.
  3. local static: Same problem as #2.

The only solution I have found, is to have MyObj inherit from another class

MyOtherObj{
private:
    bool _isInit = false;
public:
    bool isInit(){
          bool ret = true;
          if (!_isInit){
              ret = false;
              _isInit = true;
          }
          return ret;
    }
};

class MyObj : public MyOtherObj {
public:
    void MyFunc(){
        if (!isInit()){
            //Do stuff...
        }
    } 

};

Any better suggestion ?

EDIT: I don't care about thread safety!

EDIT: I do not want to execute the method in the constructor, simply because the method may need to be executed much later in the lifetime of the object....

Rahul Iyer
  • 19,924
  • 21
  • 96
  • 190
  • 34
    Option #1 works correctly. Simply don't modify the member variable from other functions. If you can't trust other functions, you have already lost. – Dietrich Epp Jan 27 '17 at 09:12
  • 4
    Also note that member variables should not begin with underscore. `_isInit` is not a legal choice according to the language spec. – Dietrich Epp Jan 27 '17 at 09:14
  • @DietrichEpp But is it good practice or design ? I'm trying to see that if there are many methods I want executed just once how to do it cleanly, without having many variables to keep track of this... I know I could document it etc, or maybe even store all the bools in a collection, but it doesn't seem clean to me..... – Rahul Iyer Jan 27 '17 at 09:14
  • 2
    Why don't you just execute it in the constructor of the object? – barak manos Jan 27 '17 at 09:14
  • @DietrichEpp can you explain why I cannot start a variable name with "_" ? My textbook mentioned that you can have variable names starting with _ ...... – Rahul Iyer Jan 27 '17 at 09:15
  • @barakmanos I may execute the method long after the object is created. I don't necessarily want to execute the method right in the beginning. – Rahul Iyer Jan 27 '17 at 09:16
  • You could use http://en.cppreference.com/w/cpp/thread/call_once instead of the isInit variable. This can never be reverted, unlike the bool member that could be changed somewhere else. – dydil Jan 27 '17 at 09:16
  • [what-are-the-rules-about-using-an-underscore-in-a-c-identifier](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). So currently it is ok. – Jarod42 Jan 27 '17 at 09:17
  • 2
    @Jarod42 so by that reasoning, my usage of the _ is legal as long as MyOtherObj is in its own namespace.... – Rahul Iyer Jan 27 '17 at 09:19
  • 1
    @dydil: `std::once_flag` is not copyable/movable, so it depend on if OP wants its object to be moveable/copyable. – Jarod42 Jan 27 '17 at 09:20
  • 1
    @Jarod42 - yes I would like my object to be copyable, moveable... – Rahul Iyer Jan 27 '17 at 09:23
  • @Jarod42 Didn't think about that. Is a shared pointer to a once flag too much? – dydil Jan 27 '17 at 09:33
  • @dydil: OP helper class should be enough, using `std::atomic` to handle thread safety if needed. `shared pointer` is too much IMO. – Jarod42 Jan 27 '17 at 09:36
  • 2
    @John: You should inherit privately from `MyOtherObj`, as currently you can call `isInit()` from outside of the class. – Jarod42 Jan 27 '17 at 09:40
  • The member_function should not be executed second time. What exactly do you expect even if its executed second time. Can it result in a crash? or simply the functionality inside of that function should not get executed? – sameerkn Jan 27 '17 at 09:51
  • 1
    @DietrichEpp `_i` is legal but `_I` would not be – M.M Jan 27 '17 at 09:54
  • create a static variable and make it increase when your method is called. – Mohammad Tasneem Faizyab Jan 27 '17 at 12:42
  • The first time the method is called, edit the method's instructions in memory to make the first instruction a `jmp`. – Owen Jan 27 '17 at 15:17
  • 1
    @Owen looks like you love to spend endless time on debugging – Slava Jan 27 '17 at 15:20
  • 2
    @Owen that's a `static` “solution“, not working per object. – Felix Dombek Jan 27 '17 at 16:47
  • What's wrong with the obvious `if(!haveInited) {haveInited = true; ...}` (in same class)? Do you need thread safety? – user253751 Jan 28 '17 at 01:43

6 Answers6

50

Use std::once_flag. It is not resettable from other methods (then again, if you cannot trust other methods of the same class, your development process is highly questionable), easy to use, and it is even thread-safe if you ever do care about that. It can be a bit less efficient in a single-threaded program.

#include <mutex>

class MyObj {
public:
    void MyFunc() {
        std::call_once(initFlag, [=] {
                //Do stuff...
            });
    }

private:
    std::once_flag initFlag;
};
Arne Vogel
  • 6,346
  • 2
  • 18
  • 31
  • 3
    Ah, the issue, mentioned in comments above, is that `std::once_flag` is not copyable/movable. – Chris Drew Jan 27 '17 at 13:23
  • @Chris but one could copy the flag's state in a custom copy/move ctor, if the flag can be set manually. – Felix Dombek Jan 27 '17 at 16:51
  • 3
    @FelixDombek: The point is that the flag can't be written manually. But then, what does assignment even mean for an object requiring this behavior? – Ben Voigt Jan 27 '17 at 16:52
  • @Ben you can't reset it, but you can set it via `call_once` so if the flag is already raised when the object is copied/moved, just call an empty lambda to raise the new flag too. Maybe not the most elegant way but should work if I'm not missing something here – Felix Dombek Jan 27 '17 at 16:56
  • @Felix: `one_time_init a, b; a.init(); a = b;` How do you copy the "uninited" state from `b` onto `a` during the assignment? Should you even try? *What does assignment even mean for this class?* – Ben Voigt Jan 27 '17 at 16:58
  • @Ben Good point, would probably need to reconstruct in-place. There's another problem with my idea in that you can't even query the flag's state as far as I see. So probably wouldn't even work even with those hacks... – Felix Dombek Jan 27 '17 at 17:02
21

I don't see what is wrong with Option 1. If a class has so many responsibilities that another function may accidentally mess with the is_init member variable then the class should probably be made smaller.

However, if you want to encapsulate into another class that is less error prone, rather than using inheritance, I suggest you use composition:

class FirstTime {
    bool first_time = true;
public:
    bool operator()(){
          if (!first_time) 
              return false;
          first_time = false;
          return true;
    }
};

class MyObj {
    FirstTime first_time;
public:
    void myFunc(){
        if (first_time()){
            std::cout << "First time!\n";
        }
    } 
};

Live demo.

As with Option 1, you should think about what copy/move behavior do you want. e.g Should a copy of an initialized MyObj be considered initialized?

Chris Drew
  • 14,926
  • 3
  • 34
  • 54
  • 2
    I strongly disagree with using `operator()`. – Michael Jan 27 '17 at 11:34
  • 3
    @Michael Please explain why. – CHendrix Jan 27 '17 at 12:30
  • 8
    @Michael: indeed please explain why. It might be because you want everything to be as implicit as possible and therefore think that it should be done by `operator bool()` or `operator void*()` or something, so the user writes `if (first_time)`. Or it might be because you want everything to be as explicit as possible and therefore think the user should write `if (first_time.is_the_first_time())`. Or something else. – Steve Jessop Jan 27 '17 at 12:54
  • 1
    @CHendrix Because I believe the operation should be explicit. I see it as a misuse of operator overloads. `if (first_time.is_the_first_time())` in Steve's example is pretty clunky but I would be in favour of something to that effect. – Michael Jan 27 '17 at 13:52
  • @Michael I don't see why it is misuse. I am creating a functor that returns true the first time you call it. What is operator() for if it is not for creating functors? – Chris Drew Jan 27 '17 at 16:19
  • @Michael: Then you disagree with the naming of the member variable holding the functor, not the name of the functor. That is, you'd be happy with `if (is_the_first_time())` ? – Ben Voigt Jan 27 '17 at 16:54
  • 2
    Coding standards like `operator()` vs `is_the_first_time()` are definitely out of scope for the question. Whether it makes sense for `FirstTime` to be a functor object depends on many factors not shown in this example (for example, if you have a reason to pass it to a function that handles functors or function pointers, that could justify the use of `operator()`) – Cort Ammon Jan 27 '17 at 18:03
  • 4
    @Michael I find the repetition of "first time" in both variable/class name and method quite ugly. I would prefer Yoda speech: `first_time.is_it("?")`. – Bakuriu Jan 28 '17 at 07:16
5

I see three reasonable options:

  1. Just use your option #1, a bool member variable.
  2. Create a little class for an init flag, that can be set, but not be unset.
  3. Use the public non-virtual interface (NVI) idiom, if you really want to be sure, that no-one messes with your flag.

A bool member variable

This would be my first choice. Make it private, of course. If your class has so many other data fields, that adding this new member appears painful, then this could be a sign of bad design of the entire class in the first place.

Often init() methods can be avoided completely by splitting up a class into two: A class A that contains the constructed data before the call to init() and a class B that is initialized upon construction. That way you can see if an object is initialized only by its type.

An init flag that can be set, but not reset

This class could look somewhat like this:

class InitFlag
{
public:
    void set()
    {
        isSet_ = true;
    }

    operator bool() const
    {
        return isSet_;
    }

private:
    bool isSet_ = false;
};

This way, member functions cannot mess up your flag as easily. As an author of a class, you should be able to trust your member functions enough, that they don't set this flag, unless they are called init().

The non-virtual interface idiom

You create a base class with an init() function that is public and non-virtual. This function checks, if init() has been called before, calls a private purely virtual doInit() function which is supposed to do the actual initialization and sets the init flag after that. It looks like this:

class InitializeBase
{
public:
    virtual ~InitializeBase() = default;

    bool isInit() const
    {
        return isInit_;
    }

    void init()
    {
        assert( !isInit() );
        doInit();
        isInit_ = true;
    }

private:
    virtual void doInit() = 0;

    bool isInit_ = false;
};

This has several security advantages:

  • Derived classes cannot modify isInit_.
  • Derived classes cannot call doInit(), as long as they don't make it public or protected (which would be very nasty). However, they can and must implement this function.
  • Hence doInit() function is statically guaranteed not to be called more than once, unless an assert() will trigger.
  • If you don't want the init() function to be public, then you can derive with the protected or the private attribute from InitializeBase.

The obvious drawback is that the design is more complicated and you get an additional virtual function call. For this reason the NVI idiom has become somewhat controversial.

Ralph Tandetzky
  • 22,780
  • 11
  • 73
  • 120
  • 1
    3. No need to use public inheritance, private would even be better. – Jarod42 Jan 27 '17 at 09:38
  • Can you give an example of 3 ? – Rahul Iyer Jan 27 '17 at 09:51
  • 1
    Re your third example, the "security" is trivially bypassed. Derived classes are free to call their own overrides and can even change the access to public. [Example](http://ideone.com/EpiHIW) – molbdnilo Jan 27 '17 at 10:10
  • @molbdnilo Thanks. I fixed it. – Ralph Tandetzky Jan 27 '17 at 10:20
  • wouldn't it be better to use a regular exception, since it is sufficient to leak a `NDEBUG` flag into compilation to have `assert()` disappear? – Patrick Trentin Jan 27 '17 at 10:24
  • @PatrickTrentin Roughly, `assert()` is for programming bugs, exceptions are for resource allocation failures or similar. Of course, if the (small) run-time overhead of checking the flag in release mode doesn't hurt you, then sure, throw an exception in addition to providing the assert for debug mode. You may actually use an extra `assert()`-like macro for this purpose. – Ralph Tandetzky Jan 27 '17 at 10:33
  • @RalphTandetzky in retrospective it might be better to check the flag and simply *return* in *release mode*, rather than return an exception. I can't get my head around the use of `assert()` though, since it would result in a *silent* error state. – Patrick Trentin Jan 27 '17 at 10:36
  • Surely it's a precondition violation, if the `assert()` fails. So the `assert()` should be there. The only question that remains IMHO, is what to do in release more: 1. Don't check: Garbage in => garbage out. 2. Check and throw, if there's a precondition violation. 3. Check and return on violation. I chose the first option to keep the code simple. In a real world application that should be robust against programming errors I would probably use another macro that properly reports the error and throws or returns. – Ralph Tandetzky Jan 27 '17 at 11:01
4

Here's a variant that wraps a function in a class.
Once the function is called, it's replaced with one that does nothing.

const std::function<void()> nop = [](){};

class Once
{
public:
    Once(std::function<void()> f) : m_function(f) {}
    void operator()()
    {
        m_function();
        m_function = nop;
    }    
private:
    std::function<void()> m_function;
};

class Foo
{
public:
    Foo(int x) 
        : m_function([this](){m_x += 1;}), 
          m_x(x) {}
    int get() const { return m_x; }
    void dostuff() { m_function(); }
private:
    int m_x;
    Once m_function;
};

int main()
{
    Foo f(0);
    cout << f.get() << endl; // 0
    f.dostuff();
    cout << f.get() << endl; // 1
    f.dostuff();
    cout << f.get() << endl; // 1
}
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
0

molbdnilo's answer is pretty good and was along the same lines I was thinking. I've changed a few things which I personally think makes it more idiomatic.

#include <iostream>
#include <functional>

class Once
{
    bool isDone = false;    
public:
    void exec(std::function<void()> function)
    {
        if (!isDone)
        {
            function();
            isDone = true;
        }
    }
};

class MyObj {
    Once once = Once();

public:
    void myFunc()
    {
        once.exec( []{
            std::cout << "Hello, world!";
            // do some stuff
        });
    } 
};

int main()
{
    MyObj foo = MyObj();
    foo.myFunc();
    foo.myFunc();
    foo.myFunc();
}
Community
  • 1
  • 1
Michael
  • 41,989
  • 11
  • 82
  • 128
  • This is basically a re-implementation of `std::call_once`. Also, using a lambda instead of `std::bind`ing to a private member function may be better (as it is now, what if someone calls `myFuncImpl` directly thus bypassing your check?) if there's concerns about that. If there are no such concerns, a boolean member variable is a cleaner solution anyway. – You Jan 27 '17 at 13:03
  • 1
    As mentioned in the comments, `once_flag` is not moveable or copyable. Lamdba is a better solution, thanks. – Michael Jan 27 '17 at 13:57
0

The solution at the top is very good, but this might be a better solution for an interesting special case.

I assume that the method shall only be executed once because it modifies the state of the class. For the special case that the method initializes some parts of the class, I think it is best to use an optional, either boost::optional or std::optional or std::experimental::optional, depending on what is available to you:

#include <boost/optional.hpp>

class X
{
    public:
        void init()
        {
            if( ! _x )
            {
                _x.reset( 5 );
            }
        }

    private:
        boost::optional<int> _x;
};
Markus Mayr
  • 4,038
  • 1
  • 20
  • 42