I have a proprietary MCU that does a periodic task, and wish to fill its “downtime” with other things to do. Typically, this has been done with large switch statements, which is okay, but I’m wondering if there’s a more elegant way. This is a very common pattern in the code for this particular device, so having a generic method would be nice.
So I wrote the following code, and it works, but it doesn’t currently inline the functions.
static InterlacedFunction searchFunctions[4] = {...};
typedef int (* const InterlacedFunction)(int);
template<const int numberOfWovenFunctions> int SendPacketWithWovenFunctions(
int * packet,
const int packetLength,
InterlacedFunction (&functions)[numberOfWovenFunctions],
int firstArgument = 0)
{
int returnFromLastWoven = (numberOfWovenFunctions != 0) ? (functions[0])(firstArgument) : 0;
SendData(packet[0]);
for(int i = 1; i < packetLength; i++)
{
if(i < numberOfWovenFunctions)
returnFromLastWoven = (functions[i])(returnFromLastWoven);
SendData(packet[i]);
}
return returnFromLastWoven;
}
Am I missing something, is it impossible for Clang to inline these functions or does Clang just not have the optimization yet?
In general compilers are not aggressive at inlining calls through function pointers, even when they are known at compile time.
In this case you are relying on the compiler being clever enough to unroll the loop into a block of numberOfWovenFunctions iterations, or generate a switch of the inlined functions for you, both of which are unlikely.
If you wanted to make the idiom more generic you could do so with a recursive templates (it would be a pain to write if you do not have c++11 variadic templates), though whether it actually constitutes a simplification is perhaps questionable.
i.e. you template on the list of woven function pointer values, and at each level call the woven function, store the result, call sendPacket and the recurse into the next template level with the stored result. Something like (untested):
And then in the send:
Obviously you can make is more generic.