-
Notifications
You must be signed in to change notification settings - Fork 15
Article on lambdas #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you so much for taking the time to put this together! This looks really good! I am about halfway through reading, dropping some comments below.
{ text: "Standards", link: "/resources/general/standards" }, | ||
{ | ||
text: "C++ Resources", | ||
items: [{ text: "Lambdas", link: "/resources/general/cpp/lambdas" }], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
items: [{ text: "Lambdas", link: "/resources/general/cpp/lambdas" }], | |
items: [{ text: "Lambdas", link: "/resources/cpp/lambdas" }], |
@@ -0,0 +1,365 @@ | |||
## Abstract |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
captures by reference), making lambdas ideal for short, context-dependent operations like custom comparisons, filters, | ||
or event handlers. | ||
|
||
For example: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example comes after a couple paragraphs on captures, but doesn't use any captures. Maybe it'd be good to show this code example early on, then talk about captures, then show an example using captures?
For example: | ||
|
||
```cpp | ||
// Define a function in namespace scope |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm inclined to say this comment and others can be dropped, however, if anyone strongly feels this would be helpful for beginners reading the article then it's ok to keep. I think this article is a bit more of a deep-dive than beginner content, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comments are meant to emphasize and explain the difference between the code snippets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's pretty clear from just reading the code. Thoughts?
} | ||
``` | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't try to manually insert space like this :) This will introduce inconsistency with how the site presents itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use this as a break between paragraphs. Should I use something else or avoid breaks entirely?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’d say avoid them entirely. The site styling already handled spacing between paragraphs and headers.
The basic syntax of a lambda expression looks like this: | ||
|
||
``` | ||
[captures](params) -> ReturnType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[captures](params) -> ReturnType { | |
[captures](params) -> return_type { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-_-
|
||
| ||
|
||
Each lambda expression has its own unique, unnameable type: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd recommend moving this part to a later section as it's an implementation detail that doesn't pertain to most uses of lambdas
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where should I move this to? Also, I think showing that a lambda is really similar to a struct with an operator()
is useful early on, so should I write something else here instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a later section on implementation details
- `[x...]` - Capture a pack `x` by value. | ||
- `[&x...]` - Capture a pack `x` by reference. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a cool bit of trivia and I had to go check the grammar about it. While this is technically its own special syntax in the standard, it's not different from a user perspective. Maybe these could be moved to a note along the lines of "Captures even work with packs!"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea
}(); | ||
}(); | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think another cool thing to mention in this section about captures would be that lambdas under the hood only capture what they actually use, so [&]
and [=]
can be used without fear of bloat or overhead
Lambda parameters work the same way as normal function parameters, and `auto` parameters make a lambda's `operator()` | ||
implicitly templated. | ||
|
||
If a lambda takes no parameters, the parameter list may be omitted entirely: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd probably move this to the end of the section, just so things flow more naturally (discussion about parameters followed by an example of parameters instead of a discussion of parameters followed by an example of no parameters)
- `constexpr` - Explicitly specifies that a lambda's `operator()` is a | ||
[constexpr function](https://en.cppreference.com/w/cpp/language/constexpr#constexpr_function). | ||
- Mutually exclusive with `consteval`. | ||
- Lambdas are implicitly marked `constexpr`, if possible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be helpful to link to the criteria that determines if this is possible, either directly or as a footnote
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave the rest a read, just a couple comments
- `static` - Makes a lambda's `operator()` a | ||
[static member function](https://en.cppreference.com/w/cpp/language/static#Static_member_functions). | ||
- Mutually exclusive with `mutable`. | ||
- Cannot be used if the captures list is not empty, or an explicit `this` parameter is present. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be helpful to describe why this might be useful. Also it might be worth noting the lambda -> function pointer trick in some other section, and how this works even without static
:
auto* ptr = +[]{ return 4; };
Lambdas may be given attributes that apply to their `operator()`s since C++23: | ||
```cpp | ||
auto very_important_number = [][[nodiscard]] { return 4; }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very minor style nit but I'd suggest putting a space between the attribute, and the capture block, otherwise it's just a big block of square brackets [][[
auto very_important_number = [][[nodiscard]] { return 4; }; | |
auto very_important_number = [] [[nodiscard]] { return 4; }; |
|
||
| ||
|
||
### Capturing function parameters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this section is way too niche :)
Making a type alias with an in-line lambda in a header file or module interface violates the | ||
[One-Definition Rule](https://en.cppreference.com/w/cpp/language/definition) because aliases are not a "definable item", | ||
so lambdas in them are not allowed to match with other lambda declarations in other | ||
[translation units](https://en.cppreference.com/w/cpp/language/translation_phases#Translation_process): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I can imagine problems here I'm not seeing why this is an ODR violation, because this isn't a definable https://eel.is/c++draft/basic.def.odr#15 doesn't apply. This is an ODR violation though: https://eel.is/c++draft/basic.def.odr#18.
| ||
### In-line partial specialization |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid I don't see why this is useful. It's also not really a specialization, which can be most clearly seen in the index sequence example. I would recommend keeping that example since that is a common useful pattern.
Converting to draft until ready |
No description provided.