Date: Wed, 24 Sep 2025 01:59:44 +0800
Thanks for the information. This seems like three separate topics, and
perhaps splitting them into separate papers will speed up EWG review.
Anyway, thanks for the information.
Tom Honermann <tom_at_[hidden]> 於 2025年9月24日 週三 上午1:49寫道:
> I have a paper that addresses this. Producing a revision is on my todo
> list; it needs changes to address feedback from the last EWG review and, I
> think, changes to address the new template parameter kinds added in C++26.
>
> P3324: Attributes for namespace aliases, template parameters, and lambda
> captures <https://wg21.link/p3324>
>
> Tom.
> On 9/23/25 6:24 AM, Hewill Kang via Std-Proposals wrote:
>
> Hi All,
>
> Currently, lambdas can apply attributes to annotate operator() and its
> type. For example, the following is valid syntax (
> https://godbolt.org/z/hc4Er3h9h):
>
> [] [[attr]] ([[attr]] int) [[attr]] {}; // ok
> [] [[attr]] () [[attr]] {}; // ok
> [] [[attr]] [[attr]] {}; // ok
> [] [[]] [[]] {}; // ok, empty attribute
>
> But unfortunately, attributes cannot be used in lambda capture lists:
>
> int x = 0;
> [ [[maybe_unused]] x ](int y) { return y; }; // error
> I'm wondering if it would be reasonable to allow it to support attributes?
> I can think of a practical use case where this is useful in the real
> world, which is optimizing the size of the lambda itself.
> For example, the current standard std::bind_front implementation could be
> simplified to the following:
>
> template<auto fn, typename... BindArgs>
> constexpr auto
> bind_front(BindArgs&&... bindargs) -> decltype(auto) {
> return [...boundargs(std::forward<BindArgs>(bindargs))]
> <typename Self, typename... CallArgs>
> (this Self&&, CallArgs&&... callargs) -> decltype(auto) {
> return std::invoke(fn,
> std::forward_like<Self>(boundargs)..., std::forward
> <CallArgs>(callargs)...);
> };
> }
> constexpr int add(int x, int y) { return x + y; }
> static_assert(bind_front<add>(3)(42) == 45);
> However, there is one unsatisfactory aspect here, which is that the
> members captured by the capture list cannot be optimized for overlap, which
> is a common optimization in library implementations, i.e., Empty base
> optimization.
> If we could use attributes in the capture lists, then we could simply do:
>
> template<auto fn, typename... BindArgs>
> constexpr auto
> bind_front(BindArgs&&... bindargs) -> decltype(auto) {
> return [... [[no_unique_address]] boundargs(std::forward
> <BindArgs>(bindargs))]
> <typename Self, typename... CallArgs>
> (this Self&&, CallArgs&&... callargs) -> decltype(auto) {
> return std::invoke(fn,
> std::forward_like<Self>(boundargs)..., std::forward
> <CallArgs>(callargs)...);
> };
> }
>
> So that we no longer need to make our own special storage class type to
> perform such optimization.
> I reasonably suspect there may be many more use cases for applying
> attributes in lambda capture lists.
> What do you think? Is this a good idea?
>
> Hewill
>
>
perhaps splitting them into separate papers will speed up EWG review.
Anyway, thanks for the information.
Tom Honermann <tom_at_[hidden]> 於 2025年9月24日 週三 上午1:49寫道:
> I have a paper that addresses this. Producing a revision is on my todo
> list; it needs changes to address feedback from the last EWG review and, I
> think, changes to address the new template parameter kinds added in C++26.
>
> P3324: Attributes for namespace aliases, template parameters, and lambda
> captures <https://wg21.link/p3324>
>
> Tom.
> On 9/23/25 6:24 AM, Hewill Kang via Std-Proposals wrote:
>
> Hi All,
>
> Currently, lambdas can apply attributes to annotate operator() and its
> type. For example, the following is valid syntax (
> https://godbolt.org/z/hc4Er3h9h):
>
> [] [[attr]] ([[attr]] int) [[attr]] {}; // ok
> [] [[attr]] () [[attr]] {}; // ok
> [] [[attr]] [[attr]] {}; // ok
> [] [[]] [[]] {}; // ok, empty attribute
>
> But unfortunately, attributes cannot be used in lambda capture lists:
>
> int x = 0;
> [ [[maybe_unused]] x ](int y) { return y; }; // error
> I'm wondering if it would be reasonable to allow it to support attributes?
> I can think of a practical use case where this is useful in the real
> world, which is optimizing the size of the lambda itself.
> For example, the current standard std::bind_front implementation could be
> simplified to the following:
>
> template<auto fn, typename... BindArgs>
> constexpr auto
> bind_front(BindArgs&&... bindargs) -> decltype(auto) {
> return [...boundargs(std::forward<BindArgs>(bindargs))]
> <typename Self, typename... CallArgs>
> (this Self&&, CallArgs&&... callargs) -> decltype(auto) {
> return std::invoke(fn,
> std::forward_like<Self>(boundargs)..., std::forward
> <CallArgs>(callargs)...);
> };
> }
> constexpr int add(int x, int y) { return x + y; }
> static_assert(bind_front<add>(3)(42) == 45);
> However, there is one unsatisfactory aspect here, which is that the
> members captured by the capture list cannot be optimized for overlap, which
> is a common optimization in library implementations, i.e., Empty base
> optimization.
> If we could use attributes in the capture lists, then we could simply do:
>
> template<auto fn, typename... BindArgs>
> constexpr auto
> bind_front(BindArgs&&... bindargs) -> decltype(auto) {
> return [... [[no_unique_address]] boundargs(std::forward
> <BindArgs>(bindargs))]
> <typename Self, typename... CallArgs>
> (this Self&&, CallArgs&&... callargs) -> decltype(auto) {
> return std::invoke(fn,
> std::forward_like<Self>(boundargs)..., std::forward
> <CallArgs>(callargs)...);
> };
> }
>
> So that we no longer need to make our own special storage class type to
> perform such optimization.
> I reasonably suspect there may be many more use cases for applying
> attributes in lambda capture lists.
> What do you think? Is this a good idea?
>
> Hewill
>
>
Received on 2025-09-23 18:00:00