Skip to content

Add a fluent builder API for deferred switch expressions #50

Description

@ipapadop

Motivation

The current switch factory requires the default expression before the cases:

auto ex = deferred::switch_(
  value,
  deferred::default_([] { return "unknown"; }),
  deferred::case_(10, [] { return "10"; }),
  deferred::case_(12, [] { return "12"; }));

A fluent builder could follow the structure of a native C++ switch more closely: condition first, cases next, and default last.

Proposed API

auto ex = deferred::switch_(value)
  .case_(10, [] { return "10"; })
  .case_(12, [] { return "12"; })
  .default_([] { return "unknown"; });

Until default_() is supplied, the returned object would be a non-evaluable builder. Calling default_() would produce the existing flattened switch_expression.

Design considerations

  • Preserve heterogeneous case result deduction through homogenized_type_t.
  • Preserve references to deferred variables while owning ordinary values and callables consistently with the existing factories.
  • Support both const& chaining by copying and && chaining by moving, including move-only callables.
  • Keep existing cases in declaration order.
  • Decide whether the current variadic switch_(condition, default, cases...) API remains supported for compatibility.
  • Avoid exposing the internal condition/case tuple solely to implement the builder.
  • A switch without default_() should fail to evaluate with a clear compile-time diagnostic.

Compatibility

This is potentially a major-version API direction if it replaces the existing factory. It can instead be introduced as an additional overload because switch_(condition) does not conflict with the current signature.

Acceptance criteria

  • switch_(condition).case_(...).default_(...) creates an evaluable deferred switch.
  • Existing cases, later cases, and the default branch evaluate correctly.
  • Heterogeneous branch results produce the expected variant type.
  • Mutable deferred conditions remain observable after construction.
  • Rvalue chaining supports move-only stored callables.
  • An incomplete builder cannot be evaluated.
  • Unit and integration tests cover the fluent API.
  • Public documentation explains the builder lifecycle and compatibility with the existing API.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions