Skip to content

Instantly share code, notes, and snippets.

@Nehon
Created June 12, 2019 06:38
Show Gist options
  • Save Nehon/45cf540f9fe91c207805f31a1e12190f to your computer and use it in GitHub Desktop.
Save Nehon/45cf540f9fe91c207805f31a1e12190f to your computer and use it in GitHub Desktop.
// This small snipet is something I came with to have a set of functions that you can enable or disable.
// The requirement is to have minimum overhead when the function set is disabled, so NO if(!enabled) return; in each function.
// The idea is that for each function have instead an array of function pointer of 2 elements
funcPointer[2]{noop, implem};
// the first element is actually a noop function that does nothing, the second is the proper implemenation of the function
// With this in place you can do somthing like this
funcPointer[enabled]();
// With enabled being a boolean. This will call the noop function when the functionsst is disable (enabled = false or 0)
// and the proper implem when the function set is enabled (enable = true or 1).
// Let's take a createCube example like this
void createCube(const char* name, const fvec3 position, const fvec3 size, const fvec3 color);
// have a static enabled bool declared in the scope
bool enabled = true;
// to implement the function pointer trick you'd have
// Define the function type
using CreateCubeFunc = void(*)(const char* , const fvec3 , const fvec3 , const fvec3 );
// define the array
CreateCubeFunc createCubeFuncs[2 = {
// define the noop lambda
[](const char* , const fvec3 , const fvec3 , const fvec3){},
// define the impl lambda
[](const char* name, const fvec3 position, const fvec3 size, const fvec3 color){
// actual implementation code goes here.
}
}
// then actually implements the api point that dispatch to the correct implem
void createCube(const char* name, const fvec3 position, const fvec3 size, const fvec3 color){
createCubeFuncs[enabled](name, position, size,color);
}
// Note that I used lambda for the array, but it can be done with classic function implem,
// I was looking for the most concise way a writing this.
// This works fine. Unfortunately... it's far for concise and it's bit cumbersome to declare each time you add a new api point.
// So I went ahead and experimented with macro.
// The problem was with the list of parameters, sometimes I need the list of params with "type name",
// sometimes just "type" (for the noop), somtimes just "name" for the proper call
// I tried with variadic macro attribute, but as you can't easily manipulate them, I gave up on them.
// I opted for a macro with a fixed number of params, and chose to decline it for each cases
// (0 to 5 params should be enough IMO if this is to be done for real at some point)
// here it comes
#define FUNC_4_PARAMS(name, t1, n1, t2, n2, t3, n3, t4, n4, block) \
using DefFunc_##name = void (*)(t1, t2, t3, t4); \
DefFunc_##name func_##name[2] = { \
[](t1, t2, t3, t4) {}, \
[](t1 n1, t2 n2, t3 n3, t4 n4) { block }, \
}; \
void name(t1 n1, t2 n2, t3 n3, t4 n4) { func_##name[sceneEnabled](n1, n2, n3, n4); }
// Note that it separates the type from the param name in the declaration.
// this allow you to do
FUNC_4_PARAMS(createCube, const char*, name, const fvec3, position, const fvec3, size, const fvec3, color, {
// actual implementation code goes here.
})
// and it will expand in the code we had before.
// Nice you say?
// Well I was not completely convinced...
// The obvious pro is that it's as concise as we can get, it's barely different from a classic function declaration.
// The obvious con is this macro that you have to decline for each number of parameters... and maintain over time...
// I finally opted for a more classic approach:
// Have the implementation of the funciton set declared In a define (Debug or a more fancy stuff)
// that can be toggled on or off at compilation time. And have the noop function implemented when it's not defined.
// Then I added a "if(!enabled) return" kind of runtime toggle, that will only add some overhead in debug.
// I kept this sample for further test, maybe I some point we'll find it useful, and
// someone more Macro savvy than me could come up with a more efficient macro.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment