Working around the requirement that Concurrency Runtime task results must be default-constructible and copyable

Raymond Chen

Last time, we shed light on the hidden constraints on the result type in Concurrency Runtime tasks: The result type must have a public default constructor, and it must be copyable.

But what if your desired result type doesn’t satisfy these requirements?

To work around the need for a public default constructor, you can wrap your result type inside something that does have a public default constructor, such as std::optional.

    t([]() { return T::make(); });

If you produce the result from a lambda, you can just return a T, and a std::optional<T> will be constructed from it. If you produce the result from a task_completion_event, you’ll have to use a task_completion_event<std::optional<T>>. The result of the task will be an optional<T>, and you can use the dereference operator * to extract the value. (This assumes that the task always completes with a value, which I assume it does, because that’s what it did before you started down this path.)

To work around the need for copyability, you can wrap the result in a std::shared_ptr<T>. That way, there is still only one T object, and all the continuations get the shared copy.

And since std::shared_ptr has a public default constructor, if your result type falls into both categories (lacks a public default constructor, is not copyable), you can wrap it in a std::shared_ptr<T> and solve both problems.


Discussion is closed. Login to edit/delete existing comments.

  • David Haim 0

    I will shamelessly post my library here, concurrencpp, which (although is young) does pretty much what PPL’s tasks do but in a cross platform way.

  • Rene Stein 0

    An optional type is great for this task. (pun intended) 🙂
    As an alternative, I offer in my library Result_Traits that can be specialized for concrete type.

    Specialization for Task (result for Task<Task>)

    namespace RStein::Functional
        struct Result_Traits<AsyncCpp::Tasks::Task>
          using Result_Type = AsyncCpp::Tasks::Task;
          using Default_Value_Func = typename AsyncCpp::Tasks::Task::InvalidPlaceholderTaskCreator;

    //Edit: Blog engine apparently eats some characters in the code. 🙁

Feedback usabilla icon