Skip to content

[expr.prim.lambda.closure] Conversion to function pointer doesn't account for explicit object parameter CWG2561 #5294

Description

@brevzin

Paragraphs 8 and 9 talk about what kind of function pointer a capture-less lambda is convertible to:

... has a conversion function to pointer to function with C++ language linkage having the same parameter and return types as the closure type's function call operator.

and

... The conversion function template has the same invented template parameter list, and the pointer to function has the same parameter types, as the function call operator template.

Those aren't quite right in the case of an explicit object parameter. Since this should probably work:

using P = int(*)(int);

auto f = [](this P, int i) { return i; };
auto g = [](this auto, int i) { return i; };

P pf = f;
P pg = g;

For the non-generic case, something like this:

- having the same parameter and return types as the closure type's function call operator
+ having the same parameter types (excluding the explicit object parameter, if any) and return type as the closure type's function call operator

Though wording this for the generic case is trickier since we need to skip the invented template parameter of the explicit object parameter, which might hypothetically also be used by some other parameter?

Activity

  1. cpplearner commented on Feb 14, 2022

    @cpplearner
    Contributor

    IIUC the explicit object parameter could be used in the lambda-expression. E. g.

    struct C {
        C(auto);
        void f();
    };
    
    auto lambda = [](this C c) { c.f(); }; // OK?

    IIUC if the conversion function excludes the explicit object parameter, then the above lambda would be convertible to void(*)(), and the resulting function pointer would point to a function that calls c.f() for some nonexistent c. I don't think this makes sense.

  2. jensmaurer commented on Feb 14, 2022

    @jensmaurer
    Member

    Sounds like non-editorial CWG issue material to me.

  3. brevzin commented on Feb 14, 2022

    @brevzin
    ContributorAuthor

    Sounds like non-editorial CWG issue material to me.

    Yeah, definitely. I just wasn't sure if you preferred me emailing Core or posting it here.

    And per @cpplearner's comment, the wording may not even be wrong 😄.


    Yeah, with some more thought, [](this C c) { c.f(); } has to be a void(*)(C), which I think means that the wording is correct.

  4. cmeerw commented on Apr 1, 2022

    @cmeerw
    Contributor

    But I think we still need to change

    The value returned by this conversion function is the address of a function F that, when invoked, has the same effect as invoking the closure type's function call operator on a default-constructed instance of the closure type

    as it's not clear what that would mean, e.g.

    struct C {
        C(auto) { }
    };
    
    void foo() {
        auto l = [](this C) { return 1; };
        int (*fp)(C) = l; // EDIT: originally incorrectly had void as return type
        fp(1); // same effect as decltype(l){}() or decltype(l){}(1) ?
    }
    

    (fp should instead just be the address of the function call operator?)

  5. jensmaurer commented on Apr 2, 2022

    @jensmaurer
    Member

    Why is fp a pointer to function returning void when the lambda returns int?

  6. jensmaurer commented on Apr 2, 2022

    @jensmaurer
    Member
  7. changed the title [-][expr.prim.lambda.closure] Conversion to function pointer doesn't account for explicit object parameter[/-] [+][expr.prim.lambda.closure] Conversion to function pointer doesn't account for explicit object parameter CWG2561[/+] on Apr 2, 2022
  8. added
    not-editorialIssue is not deemed editorial; the editorial issue is kept open for tracking.
    on Apr 2, 2022
  9. frederick-vs-ja commented on Nov 1, 2025

    @frederick-vs-ja
    Contributor

    This should have been resolved by #7099 (4596a87).

  10. jensmaurer commented on Nov 1, 2025

    @jensmaurer
    Member

    Ack, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    cwgIssue must be reviewed by CWG.not-editorialIssue is not deemed editorial; the editorial issue is kept open for tracking.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions