Use stateless lambdas without capturing

92 views
Skip to first unread message

David Krauss

unread,
Dec 3, 2016, 6:47:13 AM12/3/16
to ISO C++ Standard - Future Proposals
int main() {
    auto a = []{ return 5; };
    auto b = []{ +a; a(); }; // Error, “a” not captured.
}

A stateless lambda object is empty, so it’s unfortunate that they must be captured for use by another lambda. In this case, b cannot be stateless.

C++17 constexpr lambdas offer a partial workaround:

int main() {
    constexpr auto a = +[]{ return 5; };
    auto b = []{ +a; a(); }; // OK, “a” is a constant id-expression used with L-to-R conversion.
}

This is a bit esoteric, and it can possibly cost some performance.

Perhaps it should be permissible to call, convert, and even copy a stateless lambda from an enclosing scope. (Binding to a reference or taking an address are genuinely problematic, though. Pass-by-reference would be broken, but fortunately <algorithm> and such pass by value.)

Nicol Bolas

unread,
Dec 3, 2016, 10:46:04 AM12/3/16
to ISO C++ Standard - Future Proposals

Why is this important? If it is a stateless lambda, then there's really no reason not to just make them named functions outside of the function's scope. I fail to see why encouraging people to write a plethora of functions within another function is a good idea.

Lambdas are fine things, when taken in moderation. But I don't like us adding features that encourage people to use them more often than is strictly necessary for code-clarity and functionality purposes.

Klaim - Joël Lamotte

unread,
Dec 3, 2016, 2:01:02 PM12/3/16
to std-pr...@isocpp.org
On 3 December 2016 at 12:47, David Krauss <pot...@gmail.com> wrote:
int main() {
    auto a = []{ return 5; };
    auto b = []{ +a; a(); }; // Error, “a” not captured.
}

A stateless lambda object is empty, so it’s unfortunate that they must be captured for use by another lambda. In this case, b cannot be stateless.

C++17 constexpr lambdas offer a partial workaround:

int main() {
    constexpr auto a = +[]{ return 5; };
    auto b = []{ +a; a(); }; // OK, “a” is a constant id-expression used with L-to-R conversion.
}

This is a bit esoteric, and it can possibly cost some performance.

I tend to just make `a` static const in these cases. Not esoteric and makes perfect sense and don't need to capture.
 

Perhaps it should be permissible to call, convert, and even copy a stateless lambda from an enclosing scope. (Binding to a reference or taking an address are genuinely problematic, though. Pass-by-reference would be broken, but fortunately <algorithm> and such pass by value.)

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/DA325640-1898-4835-844F-290FC7A482BA%40gmail.com.

Arthur O'Dwyer

unread,
Dec 3, 2016, 7:07:40 PM12/3/16
to ISO C++ Standard - Future Proposals
On Saturday, December 3, 2016 at 11:01:02 AM UTC-8, Klaim - Joël Lamotte wrote:
On 3 December 2016 at 12:47, David Krauss <pot...@gmail.com> wrote:
int main() {
    auto a = []{ return 5; };
    auto b = []{ +a; a(); }; // Error, “a” not captured.
}

I tend to just make `a` static const in these cases. Not esoteric and makes perfect sense and don't need to capture.

Right. In fact, you shouldn't even need "const", since the compiler is perfectly capable of seeing that "a" is unused except for its operator().
GCC 4.9.0+ get it exactly right: it realizes that "a" and "b" both have trivial constructors, so no code need be generated at all.
Clang 3.9 currently does a terrible job of optimizing here; it fails to omit the guard variable even for "static const auto a" — so not only does Clang generate a non-zero amount of code for this example, the code it does generate is full of function calls and atomic memory accesses!
Intel ICC 17 performs equivalently to Clang: terrible codegen.

Anyway, this seems like a Quality of Implementation issue, not a defect in the language.

HTH,
–Arthur
Reply all
Reply to author
Forward
0 new messages