std::packag...ackaged_task(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… std::packaged_task::packaged_task

okay bestie, welcome to the constructor page for std::packaged_task β€” yes, the whole entire name is std::packaged_task::packaged_task, that's not a typo, that's just how constructors roll. This lives in the C++ Standard Library and honestly? it's giving "let me wrap your callable in a little future-delivering envelope" ✨


🌸 SYNOPSIS

   packaged_task() noexcept;
(1) (since C++11)
   template< class F >
(2) (since C++11)
   explicit packaged_task( F&& f );
   template< class F, class Allocator >
(since C++11)
   explicit packaged_task( std::allocator_arg_t, const Allocator& a,
(3) (until C++17)
   F&& f );
   packaged_task( const packaged_task& ) = delete;
(4) (since C++11)
   packaged_task( packaged_task&& rhs ) noexcept;
(5) (since C++11)

πŸ’– DESCRIPTION

So like, the whole vibe of this page: constructs a new std::packaged_task object. That's it, that's the thesis. But there are five (5) whole flavors, so let's go πŸŽ€

  1. Constructs a std::packaged_task object with no task and no shared state. literally just a little empty husk, no thoughts head empty πŸ™ˆ
  2. Constructs a std::packaged_task object with a shared state and a copy of the task, initialized with std::forward<F>(f).

The allocator a is used to allocate memory necessary to store the task.

(until C++17) β€” heads up, that allocator bit is scoped to before C++17, no cap.

Also! These overloads participate in overload resolution only if std::decay<F>::type is not the same type as std::packaged_task<R(Args...)>.

And here's the vibe check: let t1, t2, ..., tN be values of the corresponding types in Args, if INVOKE<R>(f, t1, t2, ..., tN) is not a valid expression, the program is ill-formed. ⚠️ (until C++17)

If std::is_invocable_r_v<R, F, Args...> is false, the program is ill-formed. ⚠️ (since C++17)

And one big scary one, bestie, listen: if invoking f itself and invoking a copy of f behave differently, the behavior is undefined. πŸ’€ like... undefined undefined. don't do that.

  1. Same energy as above (the tied-together overloads in the synopsis are the whole 2,3) situation above), with the allocator a doing the memory-storing work.
  2. The copy constructor is deleted β€” std::packaged_task is move-only. no copying, we only move in this house πŸ’…
  3. Constructs a std::packaged_task with the shared state and task formerly owned by rhs, leaving rhs with no shared state and a moved-from task. it's a handoff, not a heist 🫢

πŸ¦‹ PARAMETERS

  • f β€” the callable target (function, member function, lambda expression, function object) to execute. the main character, the thing doing the work ✨
  • a β€” the allocator to use when storing the task. the little helper who handles the memory πŸŽ€
  • rhs β€” the std::packaged_task to move from. sorry rhs, you're giving up your stuff now 🌸

πŸ”₯ EXCEPTIONS

  • 2) Any exceptions thrown by copy/move constructor of f and possibly std::bad_alloc if the allocation fails.
  • 3) Any exceptions thrown by copy/move constructor of f and by the allocator's allocate function if memory allocation fails.

🌈 EXAMPLE

// Run this code

#include <future>
#include <iostream>
#include <thread>

int fib(int n)
{
    if (n < 3)
        return 1;
    else
        return fib(n - 1) + fib(n - 2);
}

int main()
{
    std::packaged_task<int(int)> fib_task(&fib);

    std::cout << "Starting task\n";
    auto result = fib_task.get_future();
    std::thread t(std::move(fib_task), 42);

    std::cout << "Waiting for task to finish..." << std::endl;
    std::cout << result.get() << '\n';

    std::cout << "Task complete\n";
    t.join();
}

⭐ Output

Starting task
Waiting for task to finish...
267914296
Task complete

πŸ‘‘ Defect reports

okay so the following behavior-changing defect reports were applied retroactively to previously published C++ standards. glow-ups for old code, we love to see it πŸ’–

  • LWG 2067 β€” applied to C++11. Behavior as published: the parameter type of the copy constructor was packaged_task&. Correct behavior: added const.
  • LWG 2097 β€” applied to C++11. Behavior as published: for overloads (2,3), F could be std::packaged_task<R(Args...)>. Correct behavior: F is constrained.

that's the whole page bestie, go forth and construct responsibly πŸ§šπŸ’œ

source: cppreference.com β€” version 2024.06.10 β€” std::packag...ackaged_task(3) 🌸

πŸ“¦ where this page comes from