Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

C++ Module 17

Modules and coroutines interview questions

Interview questions on modules and coroutines: short warm-ups, then what each harder question tests, the first step of a good answer and its follow-ups.

22 questions: 5 warm-ups and 17 with model answers · Levels: Fresher to staff

Warm-up questions

Short questions with short answers, each answered in full.

  1. Fresher

    What does export do in a C++ module, and what does an importer not get?

    Answered in the lesson C++20 modules: export, import and partitions

  2. Fresher to mid

    What is the difference between import std; and import std.compat;, and what does neither of them provide?

    Answered in the lesson import std in C++23: which toolchains support it

  3. Fresher to mid

    What makes a C++ function a coroutine, and what do promise_type and coroutine_handle do?

    Answered in the lesson C++ coroutines: co_await, co_yield and co_return

  4. Fresher to mid

    What is a generator in C++, and when would you return one instead of a std::vector?

    Answered in the lesson Generators: std::generator and writing your own

  5. Fresher to mid

    What do await_ready, await_suspend and await_resume do, and in which order does co_await call them?

    Answered in the lesson Async coroutines: tasks, awaitables, event loops

Questions with model answers

What each question tests, the first step of a good answer and the follow-ups to expect.

  1. Mid to senior

    Your team turns a widely used utility header into a module. Afterwards, files that used the header's MAX_RETRIES macro or its detail::parse helper stop compiling, and the CI job on Macs fails at CMake's generate step. Explain each failure and how you would fix it without reverting the change.

    What it tests
    Whether macros and non-exported names are known not to cross an import, how to expose what consumers really need, and which compilers and generators CMake can build modules with.
    First step
    Separate the three failures. A macro never leaves a named module, so MAX_RETRIES needs a new home. detail::parse is not exported, so it has module linkage. The Mac job is a toolchain problem: CMake cannot scan imports with Apple clang, so the module build needs another compiler there.
    Follow-ups

    From the lesson C++20 modules: export, import and partitions

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.

    Opening the model answers with your pass…

    Model answers open with any MySmartCoPilot pass.

    • Pro pass · 1 week₹79$2.99
    • 30 days₹179$5.99
    • 1 year₹1,699$45

    One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

    It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  2. Mid to senior

    A hand-written Makefile builds a library with three module interface units and a dozen importers. With make -j8 the build fails about one time in ten with "module not found", and always passes with make -j1. Explain the failure and how you would make the build correct.

    What it tests
    Understanding that imports impose a compile order, why parallel builds expose missing edges, and how dependency scanning in CMake with Ninja solves it.
    First step
    The error comes from an importer compiled before the module file it reads exists. With -j1 the rule order happens to work; with -j8 independent rules run together. The Makefile is missing edges from each importer to the module files of what it imports.
    Follow-ups

    From the lesson C++20 modules: export, import and partitions

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  3. Mid to senior

    Your team adopts import std;. Linux developers using GCC 16 are fine, but every Mac developer gets "module 'std' not found", although a build check shows that __cpp_lib_modules is defined. Explain what is going on and how you would set up the Macs.

    What it tests
    Knowing that a std module is built from sources the library ships, that Apple's toolchain ships none, why the feature-test macro misleads, and the workable Mac toolchains.
    First step
    Separate what the library claims from what the toolchain can build. __cpp_lib_modules comes from the library's version header; import std; needs the std module's sources, which Apple's Command Line Tools do not ship. Then pick a Mac toolchain that ships them: GCC 16 or an LLVM release.
    Follow-ups

    From the lesson import std in C++23: which toolchains support it

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  4. Senior to staff

    A build script compiles the std module once, with -std=c++23 -O2, and every target imports it. One target moves to C++26 and another adds -D_GLIBCXX_ASSERTIONS for hardening. What breaks loudly, what breaks silently, and how should std module builds be organised?

    What it tests
    Which differences between a module and its importers compilers check when they load it, what a macro on the importer can still change, and how to organise std module builds.
    First step
    Split the options into two groups: those that define the language dialect, such as -std, and macros, such as -D_GLIBCXX_ASSERTIONS. For each group, ask whether the compiler compares it with the module file's options, and what the std module's code already contains when the importer is compiled.
    Follow-ups

    From the lesson import std in C++23: which toolchains support it

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  5. Mid to senior

    Your project has 300 source files and builds with GCC 16 on Linux and with Clang and libc++ on macOS. A colleague proposes converting every file to import std;. How would you estimate whether it is worth it, and what would you measure first?

    What it tests
    Turning the one-time cost of the std module and the per-file saving into a break-even estimate, measuring CPU time properly, and knowing the saving differs by toolchain.
    First step
    Measure, do not guess: take a few representative files, compile each to an object file with #include and with import std;, and record CPU time over several runs on each toolchain, plus the one-time cost of building the std module. Then compute saved time per file times file count against that cost.
    Follow-ups

    From the lesson import std in C++23: which toolchains support it

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  6. Senior to staff

    You maintain a 500-file C++ library used by other teams on GCC, Clang and MSVC, some with older compilers and plain Makefiles. You are asked to move it to modules. Plan the migration: what you ship first, what you must never break, and how you know each step worked.

    What it tests
    Planning a gradual migration around consumers who cannot import yet, choosing ABI-preserving styles, and defining checks that prove each step changed nothing.
    First step
    Start from the consumers, not the code. Some can never import yet, so the headers and the ABI must keep working throughout. That points to wrappers first: a module per library that re-exports the existing headers, shipped beside them, with a CI build that compiles both kinds of consumer.
    Follow-ups

    From the lesson Migrating a C++ project to modules

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  7. Mid to senior

    After a teammate moved a library's declarations into its module, the link fails with undefined symbols for functions that clearly exist. nm -C on the library shows textutil::split@textutil. Explain the failure and give two ways to fix it.

    What it tests
    Understanding module attachment and its effect on linkage names, how to find the files still using the old declarations, and the extern "C++" alternative.
    First step
    Read the two names the linker is matching: the library defines split attached to the module textutil, which is what @textutil means, while some object file was compiled from the old header and asks for the global-module split. Find which objects reference the plain name, with nm on each.
    Follow-ups

    From the lesson Migrating a C++ project to modules

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  8. Mid to senior

    Users of your library select a faster code path with -DTEXTUTIL_FAST_SPLIT, which the header's inline code tests, and they check TEXTUTIL_VERSION in #if. How do you keep both working once they import the module instead of including the header?

    What it tests
    Knowing that importers' macros cannot reach a module's code, separating configuration macros from values, and moving build-time configuration to the build of the module itself.
    First step
    Treat the two macros differently. TEXTUTIL_VERSION flows from the library to the user, and #if can read it only from a header, so it moves to a small config header, with an exported constant for code. TEXTUTIL_FAST_SPLIT flows from the user into the library, and an importer's -D flags never reach code inside a module.
    Follow-ups

    From the lesson Migrating a C++ project to modules

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  9. Mid to senior

    A lazy coroutine task, Task load(const std::string& path), passes every unit test but crashes now and then in production, where it is created with a path built inside the calling function and run later by a scheduler. What is going on, and how do you fix it and keep it fixed?

    What it tests
    Understanding what the frame keeps for each parameter, why tests miss the bug, how sanitizers expose it, and which interface rules prevent it.
    First step
    Follow the string's lifetime from the call to the moment the scheduler first resumes the task. Ask two questions: what does the frame keep for a parameter of reference type, and when does a lazy task's body run compared with the end of the calling function?
    Follow-ups

    From the lesson C++ coroutines: co_await, co_yield and co_return

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  10. Mid to senior

    In a code review you see: auto task = [this, config]() -> Task { co_await fetch(); apply(config); }(); and the task is stored and run later. What is wrong with it, even though config is captured by value, and how would you rewrite it?

    What it tests
    Knowing where a coroutine lambda's captures live while it is suspended, why capturing by value does not help, the rewrite the C++ Core Guidelines recommend, and the lifetime of the captured object.
    First step
    Ask where config lives while the coroutine is suspended, and who owns that storage. The lambda is called on a temporary closure object in the same statement that stores the task; compare that object's lifetime with the moment the task is finally run.
    Follow-ups

    From the lesson C++ coroutines: co_await, co_yield and co_return

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  11. Senior to staff

    Design the return type of a coroutine used for background jobs: who owns the frame, when the body starts, how errors reach the caller and what happens if the job object is dropped. Walk through the promise hooks you would write and why.

    What it tests
    Turning the promise hooks into ownership and error-handling decisions: lazy start, final suspension, a move-only owner, exception transport and safe destruction.
    First step
    Start from ownership: which object owns the frame, and how many times may it be destroyed? Then choose what initial_suspend and final_suspend return so that nothing runs before that owner exists and nothing is freed while the owner may still read the result.
    Follow-ups

    From the lesson C++ coroutines: co_await, co_yield and co_return

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  12. Mid to senior

    A colleague's code stores pointers to the strings a generator yields in a vector inside the loop, then prints them after the loop. It printed the right names in a few tests and garbage in others. Explain what happens and how you would fix and catch it.

    What it tests
    Knowing how long a yielded value lives, that the frame itself ends with the generator, how undefined behaviour hides in tests, and the fixes.
    First step
    Ask where each string lives and when it ends. A yielded value stays valid only until the generator resumes, and the loop resumes it on every step; after the loop, the generator object itself is gone. So check what a stored pointer refers to at the moment the code after the loop reads it.
    Follow-ups

    From the lesson Generators: std::generator and writing your own

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  13. Senior to staff

    Your code base must build with GCC 16 and with Apple clang, whose library has no <generator>. How would you provide generators, and what must a hand-written Generator<T> get right in its promise, its iterator and its ownership to be safe and work with std::views?

    What it tests
    Designing a portable generator type: the promise's storage of values, exception transport, the iterator and sentinel concepts, view behaviour and move-only ownership, plus when to switch to std::generator.
    First step
    Choose the strategy first: one project-wide generator type, used everywhere, so code does not depend on which library a compiler ships. Then list the parts: a promise that records the current value and any exception, an input iterator with a sentinel, and an owner that frees the frame exactly once.
    Follow-ups

    From the lesson Generators: std::generator and writing your own

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  14. Senior to staff

    A tree traversal written as a recursive generator, where each node's generator loops over its children's generators and re-yields their values, is slow on large trees and crashes on very deep ones. Explain both problems with numbers and give two fixes.

    What it tests
    Estimating the cost of re-yielding through every level, understanding nested resumes and the stack, and knowing elements_of and the explicit-stack rewrite.
    First step
    Count the work for one value: through how many co_yield statements does a value produced at depth d pass before the consumer sees it? Add that up over the tree. Then consider what the chain of re-yielding generators does to the call stack while the innermost one runs.
    Follow-ups

    From the lesson Generators: std::generator and writing your own

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  15. Senior to staff

    A coroutine task library works in release builds, but debug builds crash with a stack overflow when a request passes through a few hundred thousand chained co_awaits, for example a long recursive retry. The library resumes the awaiting coroutine from the final awaiter. What is happening, and how do you fix it?

    What it tests
    Understanding nested resumption, symmetric transfer and how compilers implement it, and why optimisation level changes the outcome on some compilers.
    First step
    Look at how a finishing task hands control back: if its final awaiter calls continuation.resume(), each finished task in the chain is still on the stack when the next one runs. Then compare that with an await_suspend that returns the continuation's handle, and with what each optimisation level does to that call.
    Follow-ups

    From the lesson Async coroutines: tasks, awaitables, event loops

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  16. Senior to staff

    A when_all helper for coroutine tasks works in every test, but production reports a use-after-free inside the event loop, only on requests where one of the children fails. Diagnose the problem and redesign when_all.

    What it tests
    Recognising a frame destroyed while the loop still holds its handle, structured concurrency, the language rules a fix must respect, and cancellation as the faster fix.
    First step
    Follow the failing request: when the first child throws, what happens to when_all's frame and to the other children it owns? Then ask who still holds a handle to one of those children, and when it will be resumed.
    Follow-ups

    From the lesson Async coroutines: tasks, awaitables, event loops

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  17. Senior to staff

    Design a single-threaded event loop for coroutines that wait on timers and on sockets becoming readable. What does the loop store, how does it decide what to resume next, and how do you handle cancellation and shutdown?

    What it tests
    Turning awaitables into a loop: a timer queue, readiness polling, resumption order, fairness, cancellation and clean shutdown without dangling frames.
    First step
    Start from what an awaitable hands the loop in await_suspend: a coroutine handle and the event it waits for. The loop then needs one structure per kind of event, ordered timers and a set of watched sockets, and one blocking call that waits for the earliest of them.
    Follow-ups

    From the lesson Async coroutines: tasks, awaitables, event loops

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes

All C++ interview questions · The C++ track

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.