Representative interview topic

Coding interview: How does C++26 pack indexing work, and when should you provide a fallback?

CodingMedium
Offer.cc Editorial TeamPublished Updated

Question

A variadic library must read the Nth type or value while still building on compilers without C++26 support. Explain pack-indexing syntax, constraints, failure modes, feature detection, and a fallback design.

Prompt and scope

A generic library must read a fixed-position element from a type pack or function argument pack using C++26 pack indexing, while older toolchains still build. Explain expression-pack indexing, type-pack indexing, index constraints, feature detection, and compatibility implementations.

This tests language rules and engineering fallbacks; do not claim that every compiler version already implements the feature.

What interviewer is testing

  • Whether you distinguish expression-pack indexing from the pack-indexing specifier for type packs.
  • Whether you know the index must be a compile-time constant and cannot exceed the pack size.
  • Whether you use __cpp_pack_indexing for capability detection rather than guessing from a compiler name.
  • Whether a recursive or tuple fallback preserves the API contract.

Clarifying questions

  1. Are you indexing a value pack, a type pack, or a template-parameter pack?
  2. Is the index a compile-time constant or a runtime integer?
  3. Which compilers, language modes, and CI versions are supported?
  4. Should an out-of-range index fail in a constraint, or be checked by callers?
  5. Must the fallback preserve diagnostics and complexity as well as behavior?

A 30-second answer

“C++26 pack indexing selects an expression-pack element with a constant index; a type pack uses a pack-indexing specifier. The index must be a compile-time constant and cannot be out of range. A runtime integer still needs an array, tuple, or dispatch table. I would detect __cpp_pack_indexing, use direct syntax when available, use recursion or tuple operations on older compilers, and test identical bounds and API behavior.”

Step-by-step design

1. Separate the two forms

Expression-pack indexing selects a value from function arguments; type-pack indexing selects a type from template parameters. Both move positional selection into template instantiation and reduce hand-written recursion, but their syntax and subsequent use differ.

2. Require compile-time evaluation

The index is a constant expression in a non-type template parameter context. A runtime integer cannot replace it. If runtime selection is required, materialize the pack as a tuple, array, or function table and dispatch at runtime.

cpp
template <std::size_t I, class... Ts>
using type_at = Ts...[I];

template <std::size_t I, class... Ts>
constexpr decltype(auto) value_at(Ts&&... values) {
  return values...[I];
}

3. Handle empty and out-of-range packs

An empty pack has no indexable element, and an index equal to or above the pack size is invalid. A public template should reject it early with a requires constraint that keeps the index below the pack size. Tests should cover empty, first, last, and out-of-range calls.

4. Use feature detection

cppreference records the feature-test macro __cpp_pack_indexing with value 202311L. Check the macro together with the language mode, and use compiler CI when needed; a compiler version string alone is not a language capability contract.

5. Design an older-toolchain fallback

Without C++26, a type pack can use recursive templates or a tuple type-selection utility; a value pack can first form a tuple and call a positional access utility. Preserve the same bounds constraint and compile both paths in CI.

6. Evaluate the API and diagnostics

Direct pack indexing shortens implementation, but it should remain behind a stable API. Document the required standard mode, make diagnostics name the index and pack size, and benchmark compile time and generated code for both paths instead of comparing source lines alone.

Model high-quality answer

“I would first identify the indexed entity. C++26 expression-pack indexing selects a value, while a type pack uses the pack-indexing specifier; the index is a compile-time constant, so empty and out-of-range packs should fail at the constraint boundary. Detect __cpp_pack_indexing; use direct syntax on capable toolchains and recursion, tuple_element, and get on older ones behind the same API. A runtime index needs a tuple or dispatch table. Tests cover empty, boundary, out-of-range, both language modes, and both implementations.”

Common mistakes

  • Use a runtime integer as a template index → the language requires a constant → use a tuple, array, or dispatch table.
  • Check only __cplusplus feature support depends on implementation status → check __cpp_pack_indexing and CI.
  • Leave bounds implicit → errors appear deep in instantiation → constrain the interface early.
  • Implement only type packs → value-pack calls still need recursion → test both forms separately.
  • Change semantics in the fallback → toolchains behave differently → share constraints, tests, and the stable API.

Follow-up questions and responses

Can pack indexing solve runtime indexing?

No. It requires a compile-time constant. Runtime selection needs a tuple, array, function table, or another runtime dispatch structure.

Why add a requires constraint?

The language will ultimately reject an out-of-range index, but an explicit constraint gives earlier and clearer interface diagnostics and lets the fallback expose the same contract.

Is recursive fallback always slower?

No. Runtime code may optimize to the same result, while template depth, compile time, and diagnostics can differ. Validate with the support matrix and benchmarks instead of judging by syntax length.

Public sources

Related questions

Related interview tool

Use Screenshot for a coding prompt

Capture the problem, then work through the constraints, solution, code, edge cases, and complexity in order.

View the tool