There is the following template function:

template<class func, class ...Args> auto func_wrapper_to_bool(func &&_Fn, Args &&... args) { if constexpr (std::is_member_function_pointer<func>::value) return func_wrapper_to_bool(std::mem_fn(std::forward<func>(_Fn)), std::forward<Args>(args)...); else { if constexpr (std::is_same<decltype(_Fn(std::forward<Args>(args)...)), bool>::value) return [&]()->bool {return _Fn(std::forward<Args>(args)...); }; else return [&]()->bool {_Fn(std::forward<Args>(args)...); return true; }; } } 

In my code, it is required to wrap any function that returns a non-bool function that returns a bool

I have a class

 class Test { public: void switcher(int i) { std::cout << i << std::endl; std::cout << "Cool!!!" << std::endl; } }; 

In the main function, I call the function as follows:

 int main() { Test ts; auto mem_fn = func_wrapper_to_bool(std::mem_fn(&Test::switcher), ts, 1); mem_fn(); auto not_mem_fn = func_wrapper_to_bool(&Test::switcher,ts,2); not_mem_fn(); } 

When compiling, the release version of the program works fine, and when compiling, the debug version crashes when the operator is called () with not_mem_fn. What can it be connected with?

    1 answer 1

    Well, your inner

     std::mem_fn(std::forward<func>(_Fn)) 

    This is a temporary object that will obviously be destroyed even before leaving func_wrapper_to_bool . And you capture it by reference to the lambda.

    Then when calling via not_mem_fn , returned from func_wrapper_to_bool , the lambda refers to this object through a link, and it has already been destroyed. The same problem occurs with the first call - the temporary std::mem_fn(&Test::switcher) transmitted from outside is also destroyed before calling your mem_fn() .

    And the arguments are the same problem. At the time of calling func_wrapper_to_bool values 1 and 2 exist only as temporary objects. Lambda captures them by reference , and by the time of the actual calls they have already been destroyed.

    • And you do not tell me how you can solve this problem? - Fqqlt
    • @Fqqlt, you can use copy instead of capturing by reference. - MrBin
    • @Fqqlt: Capture by value. But if you start to capture everything indiscriminately by value, then you and the ts object itself will be captured by value. This means, in particular, that inside a non-mutable lambda it will become constant and you cannot call the switcher method. You have to either pass with std::ref , or do a separate processing of the first argument for the class methods. - AnT
    • I thought so over my problem and realized that for my needs only a function that wraps a class function that does not accept anything is enough, thanks to everyone for the explanation and advice, as far as I understood the "universal" wrapper for an arbitrary impossible to do, because that it is impossible to find out for which objects copying is required, and for which just capture by reference? - Fqqlt
    • one
      @Fqqlt: Not what "impossible" means? Once again, one of the options: this is the approach used in std::thread and in std::bind . Everything is always captured by value . And if the user is not satisfied with this, then he himself uses either pointers or std::ref . That is, the user himself organizes the capture of the link ("by value"), and the wrapper does not worry at all about anything and does not try to "learn" anything. All responsibility for the lifetime, etc. lies entirely on the user. - AnT