c++visual-studio-2022std-function

How do I pass an std::function as a parameter to an assignment operator?


I have recently upgraded to Visual Studio 2022 and am having problems with assignment operators and std::function.

We have a class which allows us to call a function when it is destroyed. Note that I don't want to use a finally block to solve this.

See the code below:

class CFinallyCallFunction
{
public:
    CFinallyCallFunction(const std::function<void(void)>& finallyFn) : m_finallyFn(finallyFn) {}
    ~CFinallyCallFunction() { if (m_finallyFn != nullptr) m_finallyFn(); }
    void operator=(const std::function<void(void)>& finallyFn) { m_finallyFn = finallyFn; }
protected:
    std::function<void(void)> m_finallyFn;
};

void Test()
{
    CFinallyCallFunction fn1([] {}); // Compiles
    CFinallyCallFunction fn2 = [] {}; // Error
}

The error I'm getting is this:

Error C2440 'initializing': cannot convert from 'Test::<lambda_2>' to 'CFinallyCallFunction'


Solution

  • The problem is that the definition

    CFinallyCallFunction fn2 = [] {};
    

    is using copy-initialization, not assignment.

    And because there's no direct conversion possible for a lambda to a CFinallyCallFunction object, the initialization fails.

    As a possible solution you can add a templated constructor which can take any argument and use it to initialize the member variable:

    template<typename F>
    CFinallyCallFunction(F&& finallyFn) :  m_finallyFn(finallyFn) {}
    

    Now you can use your class with any kind of callable type.


    Also please note that your assignment operator isn't typical. To allow for chained assignments it needs to return a reference to this.