'How can we change behaviour of c++ method depending on initialization parameter?
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.
Solution 1:[1]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Vegard Jervell |
