Struct Step

Struct Documentation

struct Step

One ordered step of a ScopeBlock: build a value at this scope, or enter a nested child loop block.

The design brief’s target shape is a bare alias, using Step = std::variant<BuildStep, ScopeBlock>. That is not directly expressible: ScopeBlock::steps must hold a sequence of Step (so a build interleaves with child blocks in one ordered list, per the class doc above), which means Step has to be at least forward-declared before ScopeBlock; but std::variant requires every alternative type complete at the point the variant specialization is instantiated (unlike container::vector / std::vector, which the C++17 library tolerates holding an incomplete element type up to first use &#8212; the same relaxation ScopeBlock::steps itself relies on for its self-reference). A bare using Step = std::variant<BuildStep, ScopeBlock> declared before ScopeBlock therefore cannot compile (ScopeBlock incomplete there), and a type alias cannot be forward-declared separately from its definition (no “using Step;” forward declaration exists in C++) to defer it to after ScopeBlock either.

Hence Step is a real (forward-declarable) class wrapping the variant, not a bare alias: ScopeBlock::steps holds container::vector<Step> while Step is still only forward-declared (legal, per the std::vector incomplete-type allowance above), and Step's own definition (with the variant member) follows ScopeBlock, where ScopeBlock is by then complete. This preserves the single ordered sequence of interleaved build/child-block steps the design requires, and preserves real std::variant semantics (std::holds_alternative / std::get_if / std::visit all work on Step::value) &#8212; the only change from the brief’s literal shape is the one extra wrapping layer forced by the forward-declaration ordering.

Public Functions

inline Step(BuildStep b)
inline Step(ScopeBlock b)

Public Members

std::variant<BuildStep, ScopeBlock> value