by jandeboevrie on 6/15/25, 5:26 PM with 169 comments
by vanderZwan on 6/16/25, 4:07 AM
> One thing you need to know about me is that despite working on SumatraPDF C++ code base for 16 years, I don’t know 80% of C++.
I'm pretty sure that most "why don't you just use x…" questions are implicitly answered by it, with the answer being "because using x correctly requires learning about all of it's intricacies and edge-cases, which in turn requires understanding related features q, r, s… all the way to z, because C++ edge-case complexity doesn't exist in a vacuum".
by JeanMarcS on 6/15/25, 6:58 PM
by skrebbel on 6/16/25, 7:11 AM
I think that has the same benefit as this, that the callbacks are all very clearly named and therefore easy to pick out of a stack trace.
(In fact, it seems like a missed opportunity that modern Java lambdas, which are simply syntactical sugar around the same single-method interface, do not seem to use the interface name in the autogenerated class)
by _randyr on 6/15/25, 7:52 PM
class OnListItemSelected {
OnListItemSelectedData data;
void operator()(int selectedIndex) { ... }
}
Perhaps I'm mistaken in what the author is trying to accomplish though?by tlb on 6/16/25, 10:04 AM
by comex on 6/16/25, 4:31 AM
https://gcc.godbolt.org/z/EaPqKfvne
You could get around this by using a wrapper function, at the cost of a slightly different interface:
template <typename T, void (*fn)(T *)>
void wrapper(void *d) {
fn((T *)d);
}
template <typename T, void (*fn)(T *)>
Func0 MkFunc0(T* d) {
auto res = Func0{};
res.fn = (void *)wrapper<T, fn>;
res.userData = (void*)d;
return res;
}
...
Func0 x = MkFunc0<int, my_func>(nullptr);
(This approach also requires explicitly writing the argument type. It's possible to remove the need for this, but not without the kind of complexity you're trying to avoid.)by akdev1l on 6/15/25, 10:06 PM
I haven’t used windows in a long time but back in the day I remember installing SumatraPDF to my Pentium 3 system running windows XP and that shit rocked
by noomen on 6/15/25, 7:53 PM
by spacechild1 on 6/15/25, 8:23 PM
In danger of pointing out the obvious: std::function does note require lambdas. In fact, it has existed long before lambdas where introduced. If you want to avoid lambdas, just use std::bind to bind arguments to regular member functions or free functions. Or pass a lambda that just forwards the captures and arguments to the actual (member) function. There is no reason for regressing to C-style callback functions with user data.
by mwkaufma on 6/15/25, 9:48 PM
by waynecochran on 6/15/25, 6:48 PM
void (*fn)(void*, T) = nullptr;
by bmn__ on 6/16/25, 11:28 AM
Well, HN lazyweb, how do you override the stupid name in C++? In other languages this is possible:
$ node --trace-uncaught -e 'const c = function have_name() {throw null}; c()'
$ perl -d:Confess -MSub::Util=set_subname -E 'my $c = sub() {die}; set_subname have_name => $c; $c->()'
by cherryteastain on 6/15/25, 7:22 PM
std::pair<void(*)(FuncData*), std;:unique_ptr<FuncData>>
at this stage? This implementation has a bunch of performance and ergonomics issues due to things like not using perfect forwarding for the Func1::Call(T) method, so for anything requiring copying or allocating it'll be a decent bit slower and you'll also be unable to pass anything that's noncopyable like an std::unique_ptr.by mandarax8 on 6/15/25, 8:24 PM
https://github.com/TartanLlama/function_ref/blob/master/incl...
by not-so-darkstar on 6/15/25, 6:31 PM
by petters on 6/16/25, 6:51 AM
"I don't understand it, so surely it must be very difficult and probably nobody understands it"
by CraftingLinks on 6/16/25, 5:22 AM
by jitans on 6/15/25, 6:58 PM
by pif on 6/16/25, 9:18 AM
This is the kind of (maybe brilliant, maybe great, maybe both, surely more than myself) developers I don't like to work with.
You are not required to understand the implementation: you are only required to fully understand the contract. I hate those colleagues who waste my time during reviews because they need to delve deeply into properly-named functions before coming back to the subject at hand.
Implementations are organized at different logical level for a reason. If you are not able to reason at a fixed level, I don't like to work with you (and I understand you will not like to work with me).
by mgaunard on 6/15/25, 9:58 PM
by AlienRobot on 6/16/25, 6:45 PM
From what I know about C this code probably breaks on platforms that nobody uses.
Thanks for Sumatra, by the way :D Very useful software!
by tempodox on 6/16/25, 2:33 PM
by b0a04gl on 6/16/25, 6:24 PM
by _ZeD_ on 6/16/25, 8:26 AM
in my day code + data was called a class :)
(yeah, yeah, I know closure and class may be viewed as the same thing, and I know the Qc Na koan)
by commandersaki on 6/15/25, 9:29 PM
by account42 on 6/16/25, 11:50 AM
Why place undefined behavior traps like that in your code.
by agent327 on 6/16/25, 7:32 AM
Also, sad to see people still using new. C++11 was 14 years ago, for crying out loud...
by pjmlp on 6/15/25, 8:09 PM
by mdaniel on 6/15/25, 7:01 PM