C++ Logo

sg14

Advanced search

Re: [isocpp-sg14] Introducing `Embedded Function` - A Heap-Free Function Wrapper

From: Capita Lai <capita.lai_at_[hidden]>
Date: Mon, 17 Aug 2026 16:24:41 +0800
Hi Kim,

Thanks for sharing this. I mostly lurk on SG14, so please take this as
implementation/design feedback rather than an attempt to speak for the
group.

I had a look through the implementation, and I think there is useful
implementation experience here beyond simply providing another
fixed-storage `std::function`. In particular, I find the separation of the
hot invocation path from lifetime management interesting, as well as the
explicit treatment of copyable vs. move-only wrappers, signature
qualifiers, and empty-call policy. These are all issues that an eventual
`inplace_function` design would have to confront.

There is one optimization that I think deserves another look, though: the
stateless-functor elimination.

As I understand the current implementation, an owning wrapper treats an
`is_empty_trivial` functor as stateless when it is empty, trivially default
constructible, and trivially destructible, and then does not store the
original object at all.

I don't think those properties are sufficient to establish that the object
is semantically stateless. For example:

```cpp
inline int copies = 0;

struct F {
    F() = default;

    F(const F&) {
        ++copies;
    }

    void operator()() const {}
};

static_assert(std::is_empty_v<F>);
static_assert(std::is_trivially_default_constructible_v<F>);
static_assert(std::is_trivially_destructible_v<F>);

F f;
ebd::fn<void()> fn = f;
```

`F` satisfies the current `is_empty_trivial` test, but constructing an
owning wrapper from `f` would normally construct a target object and
therefore invoke the copy constructor. Eliminating the object also
eliminates that observable effect.

More generally, an empty object does not imply that its identity or
lifetime is unobservable; `operator()` may also use `this`. So I suspect
that trying to infer semantic statelessness from representation/type traits
is difficult to make generally safe.

There seems to be some relevant WG21 work pointing in a different
direction: represent the absence of runtime callable state explicitly
rather than detect it.

* P1169 (`static operator()`):
  https://wg21.link/P1169
* P2511 (NTTP callables in type-erased call wrappers):
  https://wg21.link/P2511
* P3843 (`std::function_wrapper`):
  https://wg21.link/P3843

P3843 in particular explicitly describes a compile-time-known callable
wrapper as having no state entities. That seems like a much safer category
for this optimization than arbitrary empty functors.

So perhaps one option would be to keep the optimization for cases where
statelessness follows directly from the callable representation (static
call operator / compile-time-known callable), while storing ordinary empty
functor objects normally.

A smaller observation: I also noticed the recent issue about adding an
explicit `Alignment` parameter. I think that is worth doing. For an
inplace-only wrapper, capacity and alignment are both part of the storage
contract, and applications sometimes deliberately choose stronger alignment
than the callable itself requires.

Overall, I think Embedded Function is a useful data point for a future
`inplace_function` discussion. The full library probably explores a larger
design space than a standard `inplace_function` itself would need to
expose, but that is also what makes the implementation experience useful:
it exposes where the real policy and semantic questions are.

Thanks again for sharing it.

Best regards,
Capita Lai


ycjin_kim via SG14 <sg14_at_[hidden]> 於 2026年8月15日週六 下午8:32寫道:

> Hi SG14,
>
> My name is Kim, a developer interested in embedded systems. I'd like to
> share a project I've been working on called "Embedded Function" and get the
> group's feedback.
>
> **Project Introduction**
> `Embedded Function` is a lightweight, header-only library that provides a
> collection of heap-free polymorphic function wrappers (like `ebd::fn`,
> `ebd::unique_fn`, `ebd::fn_ref`). It's designed for resource-constrained or
> high-performance environments like game development and embedded systems.
> The library is freestanding, supports C++11 through C++26, and offers
> several performance optimizations like branch elimination and zero-stack
> overhead. It contains only one header file, so it is Godbolt friendly.
>
> **Why I'm sharing this with SG14**
> I understand that SG14 has been interested in a non-allocating
> `inplace_function` for a long time. While the `stdext::inplace_function`
> implementation exists in the SG14 repository, it seems the standardization
> effort has not progressed recently. My library aims to be a modern,
> production-ready alternative. It offers several variants (`fn`,
> `unique_fn`, `classic_fn`, `fn_ref`) to cover different use cases, similar
> to what `std::function`, `std::copyable_function`, and `std::function_ref`
> provide.
>
> I believe `Embedded Function` could serve as a valuable data point or even
> a potential reference implementation for any future standardization efforts
> in this area.
>
> **Questions for the group**
> - Does the direction of `Embedded Function` align with what SG14 envisions
> for a standard `inplace_function`?
> - Are there any features or design choices you think are missing or could
> be improved?
> - What would be the best way to contribute this work to the ongoing
> discussion?
>
> The project is open-source on GitHub:
> https://github.com/Kim-J-Smith/Embedded-Function. I'd be very grateful
> for any feedback, suggestions, or criticism.
>
> Best regards,
> Kim J. Smith
>
> _______________________________________________
> SG14 mailing list
> SG14_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/sg14
>

-- 
本郵件可能包含威旭資訊股份有限公司之機密或個人資料,僅限指定收件人閱讀與使用。如您並非收件者,請立即刪除本郵件,並勿任意使用、傳播或揭露其內容。收件人應自行確認附件與連結安全,並妥善保護郵件內容,善盡資訊安全責任。
This email may contain confidential or personal information of VICI 
Holdings, and is intended only for the designated recipient. If you are not 
the intended recipient, please delete this message immediately and refrain 
from using, disclosing, or distributing its contents. The recipient is 
responsible for verifying the safety of attachments and links, and for 
safeguarding the information in accordance with information security 
policies.

Received on 2026-08-17 08:24:56