Home > other >  Accessing captured variables through explicit this parameter in lambda
Accessing captured variables through explicit this parameter in lambda

Time:10-24

From declarations / functions / 9.3.4.6 / 6.2 (i apologize on how to cite the specific sentence from standard):

An explicit-object-parameter-declaration is a parameter-declaration with a this specifier. An explicit-object-parameter-declaration shall appear only as the first parameter-declaration of a parameter-declaration-list of either: (6.1) a member-declarator that declares a member function ([class.mem]), or (6.2) a lambda-declarator ([expr.prim.lambda]).

If this as explicit object parameter is permitted from lambda expressions, what will happen when we capture variables at the same time?

Based on my understandings, if we have lambda under the hood:

[x = 2](this auto& func) { x = 4; }();

may have the rough equivalent of:

class lambda01 {
  private:
    int x;

  public:
    constexpr lambda01(cons int& x_)
    : x{x_} {}

    constexpr void operator()(this lambda01& func) {
      func.x = 4;
    }
};
lambda04 lambda04_obj {2};
lambda04_obj.operator()();

if it's right.

For example no. 1:

int x;

// is it:
[&x](this auto& func){ x = 4; }();

assert(x == 4);

// or:
[&x](this auto& func){ func.x = 2; }();

assert(x == 2);
  • Are both expressions valid?
  • Is lambda taking l-value object parameter valid?

For example no. 2 that will print arguments in variadic:

[]<typename... Args>(const Args&... args) {
  [&](this auto func){
    /** ... **/
  };
}(1, 2, 3, 4);

From the commented expression, which one is valid?

  • (std::cout << args << '\n', ...)
  • (std::cout << func.args << '\n', ...)
  • both
  • neither

If the second choice is valid, then that would deserve another question regarding the possible parameter packs in 1 object.

In short, is it valid to use captured variables accessed with dot operator in lambda taking explicit object parameter?

CodePudding user response:

The standard doesn't allow it:

For each entity captured by copy, an unnamed non-static data member is declared in the closure type.

If it's "unnamed", then you can't name it. There's specific language that causes the name of a captured entity to be transformed into a this-based expression, but that's it.

So you can take an explicit this parameter, and names of captured entities will automatically use that. But you can't access those variables through the explicit parameter.

The only reason to explicitly take this in a lambda is to use the interfaces the standard provides: calling the lambda. AKA: recursively calling the lambda without naming the lambda.

  • Related