Simplest C++ Callback, from SumatraPDF

SumatraPDF as a PDF Reader

  • Many comments praise SumatraPDF as fast, tiny, and “just works,” especially compared to Acrobat and browser viewers.
  • Common use cases: LaTeX workflows (auto-reload on file changes, sync with editors), large/complex engineering PDFs, ebooks (epub, cbz/cbr), and keeping PDFs separate from the browser.
  • Several argue browsers are too slow and memory-hungry for big or many PDFs; others say they rarely need more than the browser viewer.
  • Some mention security: concern over lack of sandboxing vs. others noting Sumatra disables JavaScript and sanitizes text via HarfBuzz.

Why a Custom Callback Type

  • The article presents Func0 / Func1<T> (function pointer + void* userData) instead of std::function.
  • Claimed benefits:
    • Better crash stack traces than lambdas wrapped in std::function (no anonymous compiler-generated types).
    • Smaller objects, simpler implementation, faster runtime and compile times, and code the author fully understands.
  • The author explicitly avoids “fancy” modern C++ features and says they don’t understand most of C++ and prefer minimal constructs.

std::function, Lambdas, and Alternatives

  • Many argue this is an inferior reimplementation of std::function / std::function_ref / function2, which already cover this use case with type erasure and small-buffer optimization.
  • Others propose simpler alternatives:
    • Virtual interfaces (one-method classes), possibly via a templated base.
    • std::function with lambdas that just forward to named member functions to keep stack traces usable.
    • std::bind or std::bind_front for binding receivers.
  • Some note the custom design lacks perfect forwarding, can’t easily handle non-copyable types, and always heap-allocates captured data.

Performance, “NIH,” and Engineering Trade-offs

  • Critics call this “NIH” and question unbenchmarked claims of speed/size gains. They invoke Amdahl’s law and ask for numbers.
  • Supporters counter that in a one-person, performance-focused project, small bespoke utilities can be justified, and many such micro-choices can add up.
  • There’s disagreement on whether std::function’s overhead is meaningful in a GUI app.

Correctness and Portability Concerns

  • Multiple commenters flag:
    • Casting between function pointers and void* and using -1 as a sentinel pointer as undefined or at least implementation-defined on some platforms.
    • Potential trouble with control-flow integrity if function pointers are called with mismatched types.
  • Alternatives suggested: wrappers that keep types consistent, or using intptr_t/uintptr_t for sentinels instead of invalid pointer values.

C++ Complexity and Attitudes

  • The author’s remark about not knowing “80% of C++” resonates with many; experienced developers admit similar and focus on a small, stable subset.
  • Some argue you should rely on contracts, not internal implementations; others say in C++ with remote crash logs, understanding library internals and toolchain behavior is often necessary.