lundi 31 juillet 2017

How to return an object templated with lambda?

Consider the following code:

class BaseTask {
  // Implementation here
};

class BaseSubtask {
  BaseTask *_pTask;
public:
  explicit BaseSubtask(BaseTask *pTask) : _pTask(pTask) { }
  virtual void Run() = 0;
  // The rest of implementation here.
};

template<typename taFunc> class LambdaSubtask {
  taFunc _f;
public:
  explicit LambdaSubtask(BaseTask *pTask, taFunc&& f)
  : BaseSubtask(pTask), _f(std::forward<taFunc>(f))
  { }
  LambdaSubtask(const LambdaSubtask&) = delete;
  LambdaSubtask& operator=(const LambdaSubtask&) = delete;
  LambdaSubtask(LambdaSubtask&&) = delete;
  LambdaSubtask& operator=(LambdaSubtask&&) = delete;
  virtual void Run() override final { _f(); }
  // The rest of implementation here
};

Because I cannot declare a LambdaSubtask object without specifying its template type argument, and I cannot specify its template type argument because it's a lambda, I try to implement a factory method:

template<typename taFunc> inline LambdaSubtask<taFunc>
MakeLambdaSubtask(BaseTask *pTask, taFunc&& f) {
  return { pTask, std::forward<taFunc>(f) };
}

Unfortunately this gives a compilation error:

copy-list-initialization of LambdaSubtask<lambda_...> cannot use an explicit constructor

With a proper factory method I could get a LambdaSubtask object as follows:

BaseTask task; // Initialization of the task is skipped in the example
auto&& lst = MakeLambdaSubtask(&task, [/* Capture here*/]() {
  // Implementation here
});

So basically I want a local variable object of LambdaSubtask type, with template type being a lambda. I want to avoid extra copying of anything. Surely I want to avoid std::function as my benchmarks show it's extremely slow.

Do you know how to implement a proper factory method or get local variable object of LambdaSubtask type in another way?

My compiler is MSVC++2017 with toolset v141 , so C++11/14/17 is partially supported.

Aucun commentaire:

Enregistrer un commentaire