19/10/2010 Safe indirection table in C++

I prefer static language typing for many of the same reasons I prefer static linking -- find as many things as possible before execution. John Carmack

It's always a pleasure to quote our heroes expecially when it's so true! Across the years, I became an addict of asserts and static asserts because it allows to find as many bugs as possible as early as possible which is particularly time saving.

I use a lot of indirection tables for a lot of different cases where from a value A, I want a value B. An indirection table is almost as fast as it can get and I think it should be considered before any other strategy.

A code is alive and one of the main problem with indirection table is to be sure that the size of the table match the number of input values along its life. If the input number of input value changes, the table size must match!

Unfortunatly, when with create an array, C++ doesn't require that the number of initialisation values matches the array size.

A convenient wait to handle this problem is to make sure that when the number of input value changes, we get an error message when we build the code: "find as many things as possible before execution".

My solution is to use a static assert and an array of the size of element is countains. The static assert compare the number of element of the input format and the actual count of elements of the array.

Following, a code sample that illustrates my solution.

'Cast' GLI compressed format values to OpenGL compressed format values:
  • ...
  • enum format
  • {
  • FORMAT_NONE,
  • DXT1,
  • DXT3,
  • DXT5,
  • ATI1N_UNORM,
  • ATI1N_SNORM,
  • ATI2N_UNORM,
  • ATI2N_SNORM,
  • BP_UF16,
  • BP_SF16,
  • BP
  • FORMAT_MAX
  • };
  • inline GLenum oglCast(format const & Format)
  • {
  • static GLenum const Cast[] = /!\ Do NOT create with the size of FORMAT_MAX, no size is perfect.
  • {
  • GL_NONE,
  • GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
  • GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
  • GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
  • GL_COMPRESSED_RED_RGTC1
  • GL_COMPRESSED_SIGNED_RED_RGTC1
  • GL_COMPRESSED_RG_RGTC2
  • GL_COMPRESSED_SIGNED_RG_RGTC2
  • GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB
  • GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB
  • GL_COMPRESSED_RGBA_BPTC_UNORM_ARB
  • };
  • BOOST_STATIC_ASSERT(
  • sizeof(Cast) / sizeof(GLenum) == FORMAT_MAX);
  • return Cast[Format];
  • }

With the upcoming C++0x, static_assert are nativement supported within the language and allows to customize the error message.

static_assert with C++0x:
  • static_assert(
  • sizeof(Cast) / sizeof(GLenum) == FORMAT_MAX,
  • "Indirection table and enum size mismatch");

One could ask: Why not a direct mapping, giving for example the value GL_COMPRESSED_RGBA_S3TC_DXT1_EXT to DXT1? A direct mapping it even more efficient but I think that an indirection table provides a way to index something else directly with the format value. For example, I want to know about the block size of the DXT1 format. It also allows to be API independant because actually I might simply want to get the Direct3D value of these formats too.

OpenGL Samples Pack 4.1.2.0 released >
< GLI 0.3.0.1 released
Copyright Christophe Riccio 2002-2016 all rights reserved
Designed for Chrome 9, Firefox 4, Opera 11 and Safari 5