In python I can write something like
class C:
def __init__(self, mode):
if mode == 0:
self.f = self.f0
elif mode == 1:
self.f = self.f2
(...)
else:
raise KeyError
def f0(self, a1, a2):
<do stuff>
def f1(self, a1, a2):
<do other stuff>
(...)
As an alternative to writing a parent class with subclasses C1
, C2
, ... that overwrite f
. The short question is: Can i do something similar in C++ without summoning Cthulhu?
Before anyone asks "why":
This is useful, for example if I have another class D
, that uses C
, because it allows the parameter mode
to simply be passed on to C
rather than writing separate cases everywhere an instance of C
is initialised.
I want to avoid a switch
or if
-tree that is evaluated every time f
is called, because f
is a small function that is called very many times in an already expensive calculation.
Thanks to @AlanBirtles and @Yksisarvinen !
The working solution I ended up with was
stuff.h
:
class C{
C(int mode);
const int mode;
double f(int i, int j, int k);
using FunctionType = double(C::*)(int, int, int);
double f0(int i, int j, int k);
double f1(int i, int j, int k);
FunctionType f_p;
};
stuff.cpp
:
C::C(int mode) : mode{mode} {
switch (mode){
case 0:
f_p = &C::f0;
break;
case 1:
f_p = &C::f1;
break;
default: throw "Non-valid mode!";
}
}
double C::f(int i, int j, int k) {std::invoke(f_p, this, i, j, k);}
double C::f0(int i, int j, int k){ <do stuff> }
double C::f1(int i, int j, int k){ <do other stuff>}
As suggested by @mch, using a template class would probably have been just as simple. However (not specified in the question) I needed this to work with a python-wrapper using pybind11
, so the above solution allowed me to avoid any trouble related to wrapping a template class.