'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