9 ms·
What he shows here is 75% of c++26's std::function_ref. It's mainly missing variadic arguments and doesn't support all types of function objects. https://githu
by mandarax8 1y ago
What he shows here is 75% of c++26's std::function_ref. It's mainly missing variadic arguments and doesn't support all types of function objects.
https://github.com/TartanLlama/function_ref/blob/master/include/tl/function_ref.hpp https://github.com/TartanLlama/function_ref/blob/master/incl...
- kjksf 1y agoI can honestly say that I couldn't write that thing in 100 years. I can't even read it. That's the fundamental problem with C++: I've understood pretty much all Go code I ever looked at. The code like the above is so obtuse that 0.001% of C++ programmers is capable of writing it and 0.01% is capable of understanding it. Sure, I can treat it as magic but I would rather not.
- spacechild1 1y agoDo you understand how your compiler works? Shouldn't you be writing assembly instead? You can't understand all internals and that's perfectly fine. Why do you even care how std::function is implemented? (Unless you are working in very performance critical or otherwise restricted environments.)
- kjksf 1y agoI've listed several reasons why I decided to write and use this implementation: - better call stacks in crash reports - smaller and faster at runtime - faster compilation because less complicated, less templated code - I understand it So there's more to it that just that one point. Did I loose useful attributes? Yes. There's no free lunch. Am I going too far to achieve small, fast code that compiles quickly? Maybe I do. My code, my rules, my joy. But philosophically, if you ever wonder why most software today can't start up instantly and ships 100 MB of stuff to show a window: it's because most programmers don't put any thought or effort into keeping things small and fast.
- spacechild1 1y agoOh, I definitely agree with some of your other points, just not the one I argued against. BTW, I would also contest that your version is faster at runtime. Your data always allocated on the heap. Depending on the size of the data, std::function can utilize small function optimization and store everything in place. This means there is no allocation when setting the callback and also better cache locality when calling it. Don't make performance claims without benchmarking! Similarly, the smaller memory footprint is not as clear cut: with small function optimization there might be hardly a difference. In some cases, std::function might even be smaller. (Don't forget about memory allocation overhead!) The only point I will absolutely give you is compilation times. But even there I'm not sure if std::function is your bottleneck. Have you actually measured?
- kjksf 1y agoThat's a fair point. I just looked and out of 35 uses of MkFunc0 only about 3 (related to running a thread) allocate the args. All others use a pointer to an object that exists anyway. For example, I have a class MyWindow with a button. A click callback would have MyWindow* as an argument because that's the data needed to perform that action. That's the case for all UI widgets and they are majority uses of callbacks. I could try to get cheeky and implement similar optimization as Func0Fat where I would have inline buffer on N bytes and use it as a backing storage for the struct. But see above for why it's not needed. As to benchmarking: while I don't disagree that benchmarking is useful, it's not the ace card argument you think it is. I didn't do any benchmarks and I do no plan to. Because benchmarking takes time, which I could use writing features. And because I know things. I know things because I've been programming, learning, benchmarking for 30 years. I know that using 16 bytes instead of 64 bytes is faster. And I know that likely it won't be captured by a microbenchmark. And even if it was, the difference would be miniscule. So you would say "pfft, I told you it was not worth it for a few nanoseconds". But I know that if I do many optimizations like that, it'll add up even if each individual optimization seems not worth it. And that's why SumatraPDF can do PDF, ePub, mobi, cbz/cbr and uses less resources that Windows' start menu.
- 1y ago
- maleldil 1y ago> You can't understand all internals, and that's perfectly fine. C++ takes this to another level, though. I'm not an expert Go or Rust programmer, but it's much easier to understand the code in their standard libraries than C++.
- spacechild1 1y agoFair enough :) Unfortunately, this is just something one has to accept as a C++ programmer. Should we roll our own std::vector because we can't understand the standard library implemention? The answer is, of course, a firm "no" (unless you have very special requirements).
- mandarax8 1y agoYeah it's a shame that to go from your idea to something that's 'general' (ie just some arbitrary arguments) you need to write this arcane garbage.
- winocm 1y agoConsider this implementation: https://llvm.org/doxygen/STLFunctionalExtras_8h_source.html https://llvm.org/doxygen/STLFunctionalExtras_8h_source.html
- moonshadow565 1y agoIt's not that complex if you remove all the stuff you don't use: https://godbolt.org/z/rM9ejojv4 https://godbolt.org/z/rM9ejojv4 . Main things you would need to understand is specialization (think like pattern matching but compile time) and pack expansion (three dots).