I've done baby, I've totally done it. It's just awesome so stuff working like expected, PLUS the system is ready for serious meta programming! Fuck, I never thought of ever getting it to work in C++. My current experiment involves set of "function classes" that provide a static execution function with a set layout, possibly implicitely parameteized when using a teplate function instead. In the current test environment it's a set of operator functions, similar to globally overloaded operators. They are only compound operators, but combined with a class providing two functions that take these function classes as template parameters, you can a) call the exec() function of the provided function class and b) generate a normal operator for EACH defined compound-operator. It's like a normal operator call, just with a different name and usage.

Usage is quite simple though much more complex to read. This simple statement:

c = a + b

Would be written as the following:

c.compOp<Set> ( a.op<Add> (b) );

You see, it's basically the same but in function notation and by using names for the operator type and template parameter for the operation to execute. The awesome about is that the operation you give it can be executed INLINE, thus no overhead as opposed to calling functions RTTI- oder callback-based. Provided your compiler settings enable excessive inline use, you can pass any function class matching the calling convention inside the compOp/op method without any overhead. That's fucking great for a number advantages, not only limited to operator-style use:
  • write filling functions for arrays without repeating for-loops on and on again
  • create a couple of "shape tracers" for your array and fill it with a special filling function like
  • save time in implementing more features for the two above
  • insert any code you want anywhere
  • ensure consistency along the code that's shared by a series of functions in general (like alpha vs. additive blending or so)
  • etc etc etc
That said, you can some really interesting things, though limited but still amazingly useful. And for you debugging fetishist: You can still deactivate optimizations and use stack tracing etc for even more sophisticated debugging (opposed to "reincarnating" shared code over and again, generating mistakes if you change and need to do the same for the rest).
And yes, it's fucking typesafe, though it only complains when you instanciate the function. Much better than I expected from it. You can even parameterized a function class to execute another parameter-defined function class inside the previous function class. So it's all up to you making whatever you can chain and imagine. Geez, I love that. Using this I can continue my old work right from here where I stay! That was a huge step closer to my dream of getting the most quick and flexible software renderer I can write without getting too deep into lowlevel optimization and case-specific assembler code and so on. If I think about, there are so much more things I can simplify using this. First of all, it's the "poor man's" polymorphism during compile time, but no overhead during execution (provided you active optimization and inline of course). That means I can use to do all the stuff I was only able to do using virtual members before I create this little awesome technique. I'm not even scratching the surface, nor do I really know what doother than for array operations etc. Time will show it's real use, I bet. So far, it does seem to do a great job for what it was created. I'll writing a series of function classes I could think of and see what else comes to mind. Geez, this way I can implement so many things I couldn't before. That's almost all I ranting and beefing about before...

Wait, take abreak. Gonna choke in whole first. No good idea to feel rushed for posibilites, but rather by actually done stuff... However, I can't wait to use it!

No comments: