Created
June 12, 2019 06:38
-
-
Save Nehon/45cf540f9fe91c207805f31a1e12190f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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