Any non-trivial thing to do is a pain to figure out if the documentation is not extensive enough.
I really love C#, but msbuild is one of the weak links to me, almost everything else is a joy to use.
Any non-trivial thing to do is a pain to figure out if the documentation is not extensive enough.
I really love C#, but msbuild is one of the weak links to me, almost everything else is a joy to use.
I’ve implemented something like this before, without macros. It’s a little ugly, but not that bad IMO.
If you write a native range-based for loop:
for (auto foo : obj) { /* do something */ }
it essentially desugars to auto it = foo.begin();
auto end = foo.end();
for (; it != end; ++it) {
auto foo = *it;
/* do something */
}
To make it work with a custom type, you need to implement `begin()` and `end()` methods, but the returned objects don’t need to support the full STL iterator protocol; they only need to support the exact sequence of operations from the desugaring. So, for example, `end()` can return a unique `End` type that contains no data and does nothing. `begin()` can return a different type that does all the real work and implements `operator!=(End)`. With that, it’s not too hard to implement a wrapper around a Python-like iterator protocol.The main drawback is that you need to temporarily store each item in the begin object before it’s moved into the iteration variable. This is because you have to already know whether a next item exists at the point of `it != end`, but then the item isn’t actually retrieved until `*it`. The extra move has a slight cost, but the compiler can often optimize it away to nothing. You can also avoid this if the for loop uses a reference type (`for (auto& foo : obj)`).
The main issue is that gpr allocation is static and worse case. So on the majority of hardware you hose your occupancy.
C++ build systems are notoriously brittle. When porting a project to a new platform, you're never just porting the code, you are also porting your build system. Every single project is bespoke in some way, sometimes because of taste, but most of the time because of necessity.
It works because people spend a huge amount of time to make it work.
It’s the same build system for all of them.
Then you top it on with `?` shortcut and the functional interface of Result and suddenly error handling becomes fun and easy to deal with, rather than just "return false" with a "TODO: figure out error handling".
here's my implementation from a while back with `setTimeout` like semantics; used it to avoid prop-drilling in an internal dashboard (sue me)
https://gist.github.com/thewisenerd/768db2a0046ca716e28ff14b...
sub => ref = 0
sub => ref = 1
unsub(0)
sub => ref = 1 (two subs with same ref!)
https://github.com/mattdesl/png-tools
I’ve also added some other features like multi-threaded encoding, cancellation, encoding physical dimensions, color profiles, all of which is useful for encoding large print-ready PNGs on the client.
(No shade against fast-png, it’s a good library, but maybe not the fastest!)
Only working on grayscale 16bit images with only the lower 10bits populated I never found it reduced image size. But I was doing per scan adaptive filtering so maybe if I was only allowed one filter for the entire image that would be it?
Just wondering if you did any experiments with different filter strategies?
Alternative is bresenham then for each point iterate a span in the minor axis.