5 ms·
How is Func0 / Func1<T> better than std::function? Smaller size at runtime (uses less memory). Smaller generated code. Faster at runtime. Faster compilation
by kjksf 1y ago
How is Func0 / Func1<T> better than std::function?
Smaller size at runtime (uses less memory).
Smaller generated code.
Faster at runtime.
Faster compilation times.
Smaller implementation.
Implementation that you can understand.
How is it worse?
std::function + lambda with variable capture has better ergonomics i.e. less typing.
- akdev1l 1y agoI think none of these points are demonstrated in the post hence I fail to visualize it Also I copy pasted the code from the post and I got this: test.cpp:70:14: error: assigning to 'void ' from 'func0Ptr' (aka 'void ()(void *)') converts between void pointer and function pointer 70 | res.fn = (func0Ptr)fn;
- cryptonector 1y ago> test.cpp:70:14: error: assigning to 'void ' from 'func0Ptr' (aka 'void ()(void *)') converts between void pointer and function pointer 70 | res.fn = (func0Ptr)fn; This warning is stupid. It's part of the "we reserve the right to change the size of function pointers some day so that we can haz closures, so you can't assume that function pointers and data pointers are the same size m'kay?" silliness. And it is silly: because the C and C++ committees will never be able to change the size of function pointers, not backwards-compatibly. It's not that I don't wish they could. It's that they can't.
- akdev1l 1y agoIt’s not a warning, it’s a compile time error and I am not even using -Wall -Werror I also believe there are platforms where a function pointer and a data pointer are not the same but idk about such esoteric platforms first hand (seems Itanium had that: https://stackoverflow.com/questions/36645660/why-cant-i-cast-a-function-pointer-to-void https://stackoverflow.com/questions/36645660/why-cant-i-cast...) Though my point was only that this code will not compile as is with whatever clang Apple ships* I am not really sure how to get it to compile tbqh Some further research ( https://www.kdab.com/how-to-cast-a-function-pointer-to-a-void/ https://www.kdab.com/how-to-cast-a-function-pointer-to-a-voi...) suggest it should be done like so: > auto fptr = &f; void a = reinterpret_cast<void &>(fptr); edit: I tried with GCC 15 and that compiled successfully
- comex 1y agoIt should just be res.fn = (void *)fn; `res.fn` is of type `void *`, so that's what the code should be casting to. Casting to `func0Ptr` there seems to just be a mistake. Some compilers may allow the resulting function pointer to then implicitly convert to `void *`, but it's not valid in standard C++, hence the error. Separately from that, if you enable -Wpedantic, you can get a warning for conversions between function and data pointers even if they do use an explicit cast, but that's not the default.
- gpderetta 1y agoFWIW, POSIX practically requires void otr and function otr inter-convertibility hence the support from GCC.
- wahern 1y agoNot practically, but literally: Note that conversion from a void * pointer to a function pointer as in: fptr = (int (*)(int))dlsym(handle, "my_function"); is not defined by the ISO C standard. This standard requires this conversion to work correctly on conforming implementations.
- gpderetta 1y agoI remembered the dlsym requirement, I wasn't sure it was de-jure.
- kjksf 1y agoThanks, fixed. It works in msvc but as someone pointed out, it was a typo and was meant to be (void*) cast.
- almostgotcaught 1y agoYour Func thing is better than std::function the same way a hammer is better than a drill press... ie it's not better because it's not the same thing at all. Yes the hammer can do some of the same things, at a lower complexity, but it can't do all the same things. What I'm trying to say is being better than x means you can do all the same things as x better. Your thing is not better, it is just different.
- spacechild1 1y agoYou can't just keep claiming these things without providing evidence. How much faster? How much smaller? These claims are meaningless without numbers to back it up.
- oezi 1y agoI think the one key downside for std::function+lambda which resonated with me was bad ergonomics during debugging. My unanswered question on this from 8 years ago: https://stackoverflow.com/questions/41385439/named-c-lambdas-for-profiling-and-debugging https://stackoverflow.com/questions/41385439/named-c-lambdas... If there was a way to name lambdas for debug purposes then all other downsides would be irrelevant (for most usual use cases of using callbacks).
- neobrain 1y ago> If there was a way to name lambdas for debug purposes then all other downsides would be irrelevant (for most usual use cases of using callbacks). Instead of fully avoiding lambdas, you can use inheritance to give them a name: https://godbolt.org/z/YTMo6ed8T https://godbolt.org/z/YTMo6ed8T Sadly that'll only work for captureless lambdas, however.
- zack-alex 1y ago[dead]
- m-schuetz 1y agoNone of the arguments on this list seem convincing. The only one that makes sense was the argument that it helps identify the source of a crash. How much smaller is it? Does it reduce the binary size and RAM usage by just 100 bytes? Is it actually faster? How much faster does it compile? 2ms faster?
- kjksf 1y agoI didn't write that article to convince anybody. I wrote it to share my implementation and my experience with it. SumatraPDF compiles fast (relative to other C++ software) and is smaller, faster and uses less resources that other software. Is it because I wrote Func0 and Func1 to replace std::function? No. Is it because I made hundreds decisions like that? Yes. You're not wrong that performance wins are miniscule. What you don't understand is that eternal vigilance is the price of liberty. And small, fast software.
- pwagland 1y agoThis is a valid point missed by many today. The mantra of don't optimise early is often used as an excuse to not optimise at all, and so you end up with a lot of minor choices scattered throughout the code with all suck a tiny bit of performance out of the system. Fixing any of these is also considered to be worthless, as the improvement from any one change is miniscule. But added up, they become noticeable.
- SuperV1234 1y ago> Is it because I made hundreds decisions like that? Yes. Proof needed. Perhaps your overall program is designed to be fast and avoid silly bottlenecks, and these "hundred decisions" didn't really matter at all.
- fsloth 1y agoIn my experience performance comes from constant vigilance and using every opportunity to choose the performant way of implementing something. Silly bottlenecks are half of the perf story in my experience. The other half are a billion tiny details.
- badmintonbaseba 1y ago> Smaller size at runtime (uses less memory). Yours is smaller (in terms of sizeof), because std::function employs small-buffer optimization (SBO). That is if the user data fits into a specific size, then it's stored inline the std::function, instead of getting heap allocated. Yours need heap allocation for the ones that take data. Whether yours win or lose on using less memory heavily depends on your typical closure sizes. > Faster at runtime Benchmark, please.