Lambda capture pattern matching

To find and replace a lambda capture, create a struct that inherits publicly from bronto::rewrite_lambda_capture and use the BRONTO_BEFORE() and BRONTO_AFTER() annotations to identify captures and define their replacements.

Example
struct RewriteCapture : bronto::rewrite_lambda_capture {
  // Matches any capture of a variable of type `int` by value.
  BRONTO_BEFORE()
  void before(int x) { [x] {}; }

  // Rewrites it to capture by reference.
  BRONTO_AFTER()
  void after(int x) { [&x] {}; }
};

BRONTO_BEFORE

Requirements

Each struct inheriting from bronto::rewrite_lambda_capture must have one member function marked BRONTO_BEFORE(). This function must contain a single lambda expression with exactly one capture.

Semantics

The capture in the lambda expression defines the pattern to be matched. This includes the capture kind (by value [x] or by reference [&x]) and the type of the captured variable.

Both explicit and implicit captures (from a capture-default) can be matched. For example, if the pattern specifies a capture by value [x], it will match:

  • Explicit captures by value: [x] { ... }
  • Implicit captures by value when [=] is used: [=] { ... x; }

Parameters

The function parameters are used to match the type of the captured variable. If a parameter name is used in the capture list, it acts as a "hole" that binds to the captured variable.

BRONTO_AFTER

Requirements

Each struct inheriting from bronto::rewrite_lambda_capture may have one member function marked BRONTO_AFTER(). This function must contain a single lambda expression with exactly one capture representing how a matching capture should be transformed.

Semantics

The capture in the BRONTO_AFTER lambda defines the replacement for the matched capture. The captured variable name will remain unchanged, but its capture kind can be modified (e.g., from [x] to [&x]) or initialization added (e.g. from [&x] to [x = expr]).

Limitations

  • Rewriting this or *this captures is not supported.
  • Matching init-captures (e.g., [x = expr]) is not presently supported.

Use as a Usage Constraint

bronto::rewrite_lambda_capture can also be used as a nested struct within a bronto::rewrite_decl rule using BRONTO_USAGE. This allows you to specifically target and rewrite how a particular variable is captured when it is used within a lambda.

Usage Constraint Example
struct Rule : bronto::rewrite_decl {
  BRONTO_BEFORE()
  void before(auto expr) { int x = expr; }

  struct BRONTO_USAGE(allowed) Capture : bronto::rewrite_lambda_capture {
    // Match any time this specific variable `x` is captured by value.
    BRONTO_BEFORE()
    void before(int x) { [x] {}; }

    // And rewrite it to be captured by reference.
    BRONTO_AFTER()
    void after(int x) { [&x] {}; }
  };
};

See it in action on compiler explorer

On this page