I was playing around with rust and wondered if I could use const generics for toggling debug code on and off to avoid any runtime cost while still being able to toggle the DEBUG flag during runtime.
I came up with a nifty solution that requires a single dynamic dispatch which many programs have anyways.
It works by rewriting the vtable.
It's a zero cost bool!
It really is not. Dynamic dispatch has a cost on every access due to it being a pointer. Instead if doing a bool check you are needing to read a pointer to figure out which function to call. I doubt this is any faster than just having the bool check and I doubt that the bool check is slowing anything down by a noticeable amount. All of this is probably not worth the complexity, especially without benchmark results as I can see this actually slowing down the code overall.
There is also a increased binary size due to there needing to be two versions of the code block - if you have that in every function that would be a dramatic increase in the binary size. This means more data needs to be loaded into memory at startup and I don't know if the branch prediction in your CPU worth with vtables?
Maybe if you already need dynamic dispatch for something it might be worth it. But most of the time I would avoid it if possible which means this pattern has a very limited usecase that you cannot use over the whole program? What is wrong with the standard logging crates in rust? I would expect them to be good enough even for game dev.
I'm stating the obvious here, but if you have ownership at the time of conversion, then you can just change the type, you don't have to use dyn (a la impl Foo<false> { fn into_debug(self) -> Foo<true> {} }). That may require some code restructuring of course.
I would move all struct members from Foo<false> into a “new” Foo<true> and return that?
Yes... if you don't define Drop for Foo.
If you do, then you will have to either use mem::take()/mem::replace() with each field, or if you don't mind unsafe {}, you can just do a trivial transmute. Justunsafe { transmute(self) } should work.