Skip to content
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

[inplace_function] Giant Sized Buffers Required for Compilation #160

Open
victorstewart opened this issue May 3, 2019 · 5 comments
Open

Comments

@victorstewart
Copy link

victorstewart commented May 3, 2019

I can generate some example cases if you guys are unaware of this circumstance, but just wanted to bring it up to confirm.

All my inplace functions are usually at most a few hundred bytes, but sometimes in order to compile one will suddenly require like 10,000 bytes! (so about 2 orders of magnitude more space). I suspect it's when you have inplace functions inside inplace functions (but leaving certainty on that aside for now).

@Quuxplusone
Copy link
Contributor

Quuxplusone commented May 3, 2019

I can generate some example cases if you guys are unaware of this circumstance

Yes please. http://sscce.org

inplace_function should only ever need ~16 bytes more Capacity than the sizeof the object you're trying to store in it. So it should never require Capacity=10000 unless you're trying to store something big — like, say, [r = std::mt19337()]() { return r(); }.

@Quuxplusone
Copy link
Contributor

@victorstewart, were you able to reproduce the issue?

@victorstewart
Copy link
Author

sorry! been so busy with my beta :). i’ll get you those test cases this weekend

@tomjwaldron
Copy link

tomjwaldron commented Jul 20, 2021

I ran into this issue. Might be a little contrived, I'm not sure, but here's an example where std::function works fine but stdext::inplace_function doesn't: https://godbolt.org/z/KcfYsvd15
error: static_assert failed due to requirement 'sizeof((lambda at <source>:26:21)) <= 32UL' "inplace_function cannot be constructed from object with this (large) size"

@Quuxplusone
Copy link
Contributor

@tomjwaldron: Agreed, and expected. Here's your example reduced even further: https://godbolt.org/z/6Wac8s938

stdext::inplace_function<void()> f;
stdext::inplace_function<void()> g = f;  // OK
stdext::inplace_function<void()> h = [f]() { f(); };  // error

Since inplace_function doesn't heap-allocate, it needs to have enough room inside its own memory footprint to store whatever callable you're putting into it. If you put in something bigger than the inplace_function itself (such as a lambda capturing an inplace_function by value), then of course that won't work — and inplace_function specifically refuses to heap-allocate any more space to hold that big callable. (Its stubborn compile-time refusal to heap-allocate is "a feature, not a bug.")

One way to (work around, fix) your original code would be to make two sizes of type-erased functions: one to hold callbacks, and one to hold lambdas-that-capture-the-first-kind. https://godbolt.org/z/9xEYPM75W

    using SmallerEventFunction = stdext::inplace_function<void()>;
    using EventFunction = stdext::inplace_function<void(), sizeof(SmallerEventFunction)>;

This guarantees that std::is_constructible_v<EventFunction, SmallerEventFunction>.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants