3 ms·
Say you have: template<typename T> void foo(T& value) { value += 42; } There's no easy way to tell the C++ compiler, "please make only one version of
by pizlonator 4y ago
Say you have:
template<typename T>
void foo(T& value) { value += 42; }
There's no easy way to tell the C++ compiler, "please make only one version of foo and use callbacks to figure out what it means to += on T".
In libpas, this would be done by first creating:
always_inline void foo(void* value, void (*add_int)(void* value, int addend))
{
add_int(value, 42);
}
And then you could also create:
never_inline void foo_outline(void* value, void (*add_int)(void* value, int addend)) { foo(value, add_int); }
Now, if you want monomorphization like C++, call foo() and pass a literal for add_int. But if you don't, then call foo_outline.
Say you have 1000 callsites to foo(), they all use different types, and 5 of those callsites are hot while the other ones are hardly ever called (maybe they only run in unusual-but-necessary situations). So, the 5 hot callsites can call foo(), and the remaining 995 cold ones cal call foo_outline().
- thrtythreeforty 4y ago> There's no easy way to tell the C++ compiler, "please make only one version of foo and use callbacks to figure out what it means to += on T". Partial counterpoint: you could use class polymorphism, if T is always a type you control. But you're right in general; C++ doesn't have typeclasses or some other way to create an ad-hoc vtable for, say, int. > Now, if you want monomorphization like C++, call foo() and pass a literal for add_int. But if you don't, then call foo_outline. Does this work through structs of function pointers? Is that the reason it's so powerful? For example, a my_class constructor create_my_class makes the class point to foo_outline, unless it's known to be a hot type, then it points to foo. When you call create_my_class, would the compiler see the values of the pointers, and start inlining foo calls, including if you pass the my_class struct into foo as "this", continuing the inlining?
- pizlonator 4y agoYes, it works with structs of function pointers. And it works recursively. This works (this is slightly shorthand C, fill in the blanks yourself): struct config { void (*foo)(things bar); stuff (*bar)(int baz); }; always_inline stuff doit(config c) { c.foo(whatever); return c.bar(42); } always_inline void my_foo(...) { ... } always_inline stuff my_bar(...) { ... } stuff dostuff(void) { config c; c.foo = my_foo; c.bar = my_bar; return doit(c); } This'll all get inlined and specialized to death.
- thrtythreeforty 4y agoGot it. That is definitely a cool insight. Thanks for sharing!