Platform layer with designated array initializers
When writing for a specific API or library, like creating an OpenGL renderer, you're going to write something like this:
When you port your renderer to something like DirectX you end up writing an equivalent function call to match the behaviour of OpenGL. You'll wrap it up in a function call like
upload_texture(...). But what about those data types, the pixel format of
GL_RGBA8 and data type of
GL_UNSIGNED_BYTES? Things the client application wants to set and look at. So you write a nice wrapper:
Then you need to convert between your own layer and the way the API wants it. Something like this?
Functional but gross, you could so easily miss a value! You could use a switch statement with a warning for unhandled cases, but you still need to have a block of code that manually does the conversions.
You get clever (uh-oh), and do something like this.
Great! You call
Platform_PixelFormat[pixel_format] and wonderful, everything maps! Except later on someone (probably spiteful future you) reorders the enum. Maybe you've added a second array to reflectively print out a pretty string with the enum value. It all goes wrong. You can assign
eRGB = 1 if you think you can trust the ordering of the platform-specific arrays which might work here, but less so when you start dealing with constants you can't easily visually verify like
Designated Array Initialisers
Still not a part of the spec but widely supported by extensions (you know, the typical 'why can't we have the nice things from C90 and beyond?` thing ^-^) are designated array initializers, which let us use enum values to map across multiple arrays. We can change our code to this:
Now we can have completely mismatched ordering between any of these types and it won't bite us layer. Two caveats:
- The enum has to be unscoped (so we dropped the
- Same as before, the size of the array will grow to fit the possible enum range. So don't set
eRGB = 0x1907unless you want roomy thousands-long arrays.
Of course then DirectX will hit you with tying its pixel formats and data types end with you writing a conversion wrapper anyway >.< But designated array initialisers will still be there to help you out, and for all of those reflective string cases!