I am writing a routine to find the numerical roots of a function in C++. Depending on the algorithm, I can supply either the function or both the function and derivative. For example, I have two separate routines
template <typename T, typename Func>
T Bisection(Func func, T x) {
// algorithm details...
auto f = func(x);
// more details...
}
template <typename T, typename Func>
T Newton(Func func, T x) {
// algorithm details...
auto [f, df] = func(x);
// more details...
}
Note that one method assumes that the Func type will be a simple one-variable function, whereas the other assumes it is some structure that contains both the function 'f' and the derivative 'df'. Both of these routines seem to work for my tests so far.
I would like to write a master routine which accepts a parameter method, which selects either of these with a switch statement. What I have in mind is:
enum Method {
Bisection, Newton
};
template <typename T, typename Func>
T find_root(Func func, T x, Method method) {
switch(method) {
case Bisection: return Bisection(func, x);
case Newton: return Newton(func, x);
default: // do other stuff...
}
}
This does not compile. If I write a routine with method = Bisection for example, I get error error: cannot decompose non-array non-class type 'const float'
because the Newton method needs a different structure for the binding, even though I am not using it. Is there a generic way I can circumvent this to allow for a uniform master method? I have another method which the user supplies the function and first and second derivative, so that structure has three components.