Search code examples
c++11callbackinitializationmemberstd-function

How do I assign to member of type std::function<bool(wxString&)>


I have a custom Dialog class (derived from wxDialog). I want to add a setter so you can set a call back function MyDialog::m_f with some function of type std::function<bool(wxString&)>. Later, the dialog will call this function. I want to be able to pass in a lambda function (otherwise I could solve my problem with ordinary function pointers). It must also be possible to call this setter multiple times, the last set value for m_f should be valid, thus erasing any previous set values (the value being a new function). But, if I declare the member m_f, does it have to be initialized in the initializer list in the constructor? For my use case that would not really work. I have to be able to set MyDialog::m_f after the dialog has been constructed (but before ShowModal is called).

Should my member m_f be a (unique) pointer to a std::function<bool(wxString&)>, so it can be set to nullptr in MyDialog::MyDialog?

My basic problem is I do not fully understand std::function. How can you make a variable of some std::function<...> type and assign a value (concrete function) to it later? What does it mean to have a variable like described which is uninitialized? How can I test whether it is (un)assigned? Is it at all possible to delay this assignment, that is: have a separate declaration and later initialization, or should a variable of std::function<...> be initialized immediately (like a const or reference)?

Thanks for any help.

BTW, the language is C++11 and we can't upgrade due to restrictions at work.


Solution

  • How can you make a variable of some std::function<...> type and assign a value (concrete function) to it later?

    std::function has a default constructor that results in an "empty" instance. In your case, just declare the data member std::function<...> m_f and don't explicitly initialize it.

    What does it mean to have a variable like described which is uninitialized?

    That depends on the type of the variable. In the std::function, it's simply unusable. If you try to inoke an empty std::function, and exception will be thrown.

    How can I test whether it is (un)assigned?

    std::function has an explicit conversion operator to bool. It evaluates to true when the object is non-empty, i.e.

    if (m_f)
      m_f(/* parameters... */);
    else
      ; // do nothing, not set yet
    

    How can you make a variable of some std::function<...> type and assign a value (concrete function) to it later?

    If you want to later assign lambda expression to the function object through a setter, you can turn this member function into a template, e.g.

    template<class Fct>
    void setCallback(Fct&& f)
    {
        m_f = std::forward<Fct>(f);
    }
    

    Another option is to pass a std::function with the desired signature to a non-template member function.