I have a template class with a read() method. It needs to call a C functions: read1()
, read2()
, read3()
etc based upon the template parameter value. Is there is a cleaner way to do this than a switch on the template value? I have tried using a MACRO:
#define READ(N) read##N##()
But this doesn't work as X is simply replaced by the C Preprocessor as 'N' resulting in "readN()"
int read1()
{
}
int read2()
{
}
int read3()
{
}
...
template <int N>
struct Reader
{
int read()
{
switch (N)
{
case 1:
return read1();
case 2:
return read2();
case 3:
return read3();
}
}
/* Doesn't work as X is simply replaced by the C Preprocessor as 'N' resulting in "readN()"
#define READ(X) read##X##()
int read()
{
return READ(N);
}
*/
};
One can
use if constexpr
instead of switch to select proper read
call:
use constexpr
lookup table, for neatness.
use, if desperate, constexpr
implementation of map, but standard ISO one is too generic and cannot be constexpr
. A map is more useful for run-time dispatching.
wrap functions into specializations of a template function, if there are only few.
Lookup table as a function pointer table:
#include <iostream>
int read1(){ return 1; }
int read2(){ return 2; }
int read3(){ return 3; }
template <int N>
struct Reader
{
static constexpr int (*read_functions[])(void) = {
nullptr,
read1,
read2,
read3,
};
static_assert(N > 0 && N < std::size(read_functions));
int read() {
return read_functions[N]();
}
};
int main()
{
Reader<3> r;
std::cout << "Read " << r.read();
}
See on godbolt. Note, with -O2 it's completely optimized out.