CodeBlanks Logo Icon CodeBlanks

Task type

Learn Task and promise types.

Task and promise type

A Task type is the return type of a coroutine and it contains a promise_type inside. The promise_type defines how the coroutine starts, finishes and returns a value.

A promise_type must have these members: get_return_object (produces the Task object), initial_suspend (suspend at start), final_suspend (suspend at finish), return_void or return_value (finish) and unhandled_exception (error). These members form the skeleton of the coroutine. If any is missing, you get a compile error.

Suspend members

initial_suspend and final_suspend decide what happens at the start and end of the coroutine. If they return std::suspend_never the coroutine runs immediately; if they return std::suspend_always it suspends.

A Task commonly uses suspend_never for initial_suspend (start immediately) and suspend_always for final_suspend (keep the frame). This way the coroutine starts, produces a value, and when it finishes the frame stays; it can be read from outside. They are also marked noexcept because final_suspend must not throw.

Practice Complete the Task promise_type

Add std::suspend_never initial_suspend() { return {}; } and std::suspend_never final_suspend() noexcept { return {}; } members into the promise_type. The code in main is ready; do not touch it.

Starter code

main.cpp
#include <iostream>
#include <coroutine>

struct Task {
    struct promise_type {
        Task get_return_object() { return {std::coroutine_handle<promise_type>::from_promise(*this)}; }
        // Add initial_suspend and final_suspend
        void return_void() { }
        void unhandled_exception() { }
    };
    std::coroutine_handle<promise_type> handle;
};

Task run() {
    co_return;
}

int main() {
    run();
    std::cout << "Task test passed";
    return 0;
}

Sample solution

main.cpp
#include <iostream>
#include <coroutine>

struct Task {
    struct promise_type {
        Task get_return_object() { return {std::coroutine_handle<promise_type>::from_promise(*this)}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void return_void() { }
        void unhandled_exception() { }
    };
    std::coroutine_handle<promise_type> handle;
};

Task run() {
    co_return;
}

int main() {
    run();
    std::cout << "Task test passed";
    return 0;
}

Expected output

Task test passed

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 the promise_type member

Question
struct promise_type { Task ____() { return {}; } };
Answer
struct promise_type { Task get_return_object() { return {}; } };

Explanation: get_return_object produces the Task object from the promise.

2 What does promise_type do?

  • It speeds up the coroutine
  • It deletes the coroutine
  • It defines the start, finish and return behaviour of the coroutine Correct answer
  • It counts the coroutine parameters

Explanation: promise_type defines the behaviour contract of the coroutine.

3 Match each member to its role

Term Meaning
get_return_object Produces the Task object
initial_suspend Start suspend
final_suspend Finish suspend
unhandled_exception Error handling

All lessons in Advanced