Lambda to function using generalized capture impossible?
Asked Answered
S

2

10

A lambda can be easily converted to std::function though this seems to be impossible when the lambda uses generalized capture with a unique_ptr. Likely an underlying std::move is missing. Is there a workaround for this or is this a known issue?

#include <iostream>
#include <memory>
#include <functional>

using namespace std;

int main()
{
    auto lambdaGeneralizedCaptureOk = [t = std::make_unique<int>(1)]()
      {
        std::cout << *t << std::endl;
      };
    lambdaGeneralizedCaptureOk();
    
    // error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete]’
    std::function<void()> lambdaToFunctionGeneralizedCaptureNok = [t = std::make_unique<int>(2)]()
      {
        std::cout << *t << std::endl;
      };
    lambdaToFunctionGeneralizedCaptureNok();
    
    return 0;
}
Sowell answered 15/11, 2022 at 15:23 Comment(2)
you should include the error message in the question. The "is it a known issue" part can be asnwered by reading the error messagePreferential
#59968294Competency
F
12

Is there a workaround for this or is this a known issue?

std::function requires that the underlying callable must be copyable, since the lambda object in your example is move-only, this is ill-formed.

It's worth noting that C++23 introduced move_only_function, which does exactly what you need

std::move_only_function<void()> lambdaToFunctionGeneralizedCaptureNok = 
  [t = std::make_unique<int>(2)]() {
    std::cout << *t << std::endl;
   };

Demo

Feculent answered 15/11, 2022 at 15:35 Comment(2)
@CaptainGiraffe Both MSVC and libstdc++ have implemented move_only_function.Bradbradan
So C++ realized that Rust had it figured out with the FnOnce / Fn / FnMut distinction and made its own version of FnOnce. It's so fascinating to see the convergent evolution of these two languages.Demarco
H
2

The workaround is to use a std::shared_ptr instead.

Hanson answered 15/11, 2022 at 15:30 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.