c++ - 如何从 C++ 中的另一个模板函数重新转换模板函数

标签 c++ templates c++17

我正在为常微分方程 (ODE) 编写求解器,并尝试实现允许用户从多个 ODE 求解器中进行选择的运行时行为,例如正向欧拉法、二阶和四阶龙格库塔法。我正在努力使用一组模板函数,以便用户可以将变量作为映射传递给求解器,其中键可以是 int。 , 一个 charstd::string .此外,关联值可以是 floatdouble .在名为 ode_solver() 的成员函数中我需要设置变量 class_func等于求解器函数之一,即 euler_method , rk2_methodrk4_method ;但是,由于这些函数没有模板化,我收到的消息是 Variable 'class_func' with type auto has incompatible initializer of type <overloaded> .我确信这是由于 C++ 不允许我为函数动态分配类型。下面提供了代码。有没有办法启用我在这个问题中尝试的行为,或者我将不得不放弃模板并只对数据类型进行硬编码?代码有问题的区域在 .hpp 文件中以所有大写字母突出显示。我正在使用 C++17 编译器。

// main.cpp
#include "test.hpp"
#include <iostream>
#include <math.h>
#include <map>
#include <tuple>

double func6(std::map<char, double> arr);

int main(int argc, const char * argv[]) {

    ODESolver q;
    // Code inputs
    std::map<char, double> inputs;
    inputs['x'] = 2.0;
    inputs['y'] = g.e;

    double unc = 0.001;
    double tol = 0.0;
    double step_size = 0.1;
    double start = 2.0;
    double stop = 3.0;
    std::string func_name("Euler");
    std::tuple<std::vector<double>, std::vector<double>> res;
    res = q.new_ode_solver(step_size, start, stop, tol, func_name,
                           inputs, func6);
}

double func6(std::map<char, double> arr)
{
    return arr['y'] * MathKernels::logr(arr['y']) / arr['x'];
}

头文件是;

class ODESolver
{
public:

    template<class char_type, class real_type, class F>
    static inline std::tuple<std::vector<real_type>, std::vector<real_type>>
    ode_solver(real_type step_size, real_type start, real_type stop,
                   real_type error, std::string func_name,
                   std::map<char_type, real_type> &inputs,
                   const F& func)
    {
        // Verify that a correct function name was passed
        if (func_name != "Euler" and func_name != "RK2" and func_name != "RK4")
        {
            std::cout << "FATAL ERROR: ODE Solver Name must be 'Euler', 'RK2' or 'RK4'" << std::endl;
            exit (EXIT_FAILURE);
        }

        // Determine which ODE Solver to use
        // - THIS IS THE PROBLEM, THE COMPILER CANNOT DEDUCE
        //   THE TYPE FROM THE STATEMENT BELOW.
        auto class_func = &ODESolver::euler_method;

        std::tuple<real_type, real_type> res;
        std::vector<char_type> keys;
        std::vector<real_type> x_var;
        std::vector<real_type> y_var;

        keys = get_keys(inputs);
        std::cout << keys[0] << std::endl;

        // Solve ODE
        x_var.push_back(inputs[keys[0]]);
        y_var.push_back(inputs[keys[1]]);
        real_type time = start;
        while (time < stop)
        {
            res = class_func(func, step_size, inputs, keys, error);
            y_var.push_back(std::get<0>(res));
            step_size = std::get<1>(res);
            x_var.push_back(time);
            time += step_size;
            inputs[keys[0]] += step_size;
            inputs[keys[1]] = std::get<0>(res);
        }
        std::tuple<std::vector<real_type>, std::vector<real_type>> value(x_var, y_var);
        return value;
    }
// ================================================================

    template<class char_type, class real_type, class F>
    static inline std::tuple<real_type, real_type>
    euler_method(real_type step_size, std::map<char_type, real_type> inputs,
                 real_type keys, real_type error,
                 const F& func)
    {
        real_type dydx = func(inputs);
        real_type value = inputs[keys[1]] + step_size * dydx;
        std::tuple<real_type, real_type> vals(value, step_size);
        return vals;
    }
// ================================================================
// ================================================================

private:
    template<class char_type, class real_type>
    static inline std::vector<char_type> get_keys(std::map<char_type, real_type> &arr)
    {
        std::vector<char_type> keys;
        for (typename std::map<char_type, real_type>::iterator it = arr.begin();
             it != arr.end(); it++)
        {
            keys.push_back(it -> first);
        }
        return keys;
    }
};

最佳答案

正如其他人提到的,您正在尝试存储函数的地址,但赋值不能分配函数模板的地址!
只需指定模板参数,因为这些参数已经存在于 ode_solver 函数模板中,(除非不需要这样做)您可以直接在 euler_method 函数模板中使用它们。快速修复看起来像:

auto class_func = &ODESolver::euler_method<char_type, real_type, F>;

同样因为它在同一个类中:

auto class_func = &euler_method<char_type, real_type, F>;

祝你好运!

关于c++ - 如何从 C++ 中的另一个模板函数重新转换模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56285173/

相关文章:

c++ - 使用imwrite OpenCV时断言失败

c++ - 范围解析运算符的评估

c++ - CUDA 测量 2 个 _syncthread() 点之间的时间

c++ - 如何从注入(inject)的 DLL 中获取程序窗口?

visual-studio - Vsixmanifest 支持 Visual Studio 2012、2013、2015

c++ - std::具有相同基类的类的变体

c++ - 编译 C++ 代码时如何解决版本控制问题?

c++ - 允许函数指针类型的模板参数接受任何返回类型的函数

c++ - C++中如何继承模板类?

c++ - 连词模板不会短路