使用类非静态成员函数进行回调

问题描述 投票:0回答:1

这有点难以描述,所以请耐心等待。我有两个独立的库,我正在尝试将它们结合起来。一个库是数值优化器(目前已实现Nelder Mead 优化器),另一个库是传感器校准库。优化器库需要用户指定并传递一个指向回调函数的指针来“优化”。传感器库有一个通用传感器类来存储各种传感器的校准数据(每个传感器一个类),并且需要调用此优化器并传递回调。但是,由于回调函数是传感器类的非静态成员,因此它会抛出“错误:无效使用非静态成员函数”之类的错误。

下面是一组非常简单的文件,作为我正在尝试做的事情的基本示例:

优化.h

#pragma once

double Optimizer(      double  (*func)(const double&),
                 const double& arg)
{
    return func(arg);
}

testLib.h

#pragma once

class Calibrator
{
public:
    double testFun(const double& arg);
    double doThing();
    
    double x = 9.8;
};

测试库.cpp

#include "testLib.h"
#include "optimize.h"

double Calibrator::testFun(const double& arg)
{
    x *= arg;
    return x;
}

double Calibrator::doThing()
{
    return Optimizer(testFun,
                     10);
}

如何解决这种情况,最好不要通过做一些古怪的事情(例如将优化器作为传感器校准类的一部分)来完全重构代码?

c++ class object callback non-static
1个回答
0
投票

因为你似乎能够修改库,

Optimizer
必须修复:

  • 旧的C兼容方式

    double Optimizer(double (*func)(void* /*userdata*/, double),
                     void* userdata,
                     double arg)
    {
        return func(userdata, arg);
    }
    

    然后

    double Calibrator::doThing()
    {
        return Optimizer(+[](void* calibrator, double d) {
            return static_cast<Calibrator*>(calibrator)->testfunc(d);
        }, this, 10);
    }
    
  • C++ 方式,无类型擦除,带模板

    template <typename F>
    requires (std::invocable<F, double>
          && std::is_convertible_v<std::invoke_result_t<F, double>, double>)
    double Optimizer(F f, double arg)
    {
        return f(arg);
    }
    
  • 或使用

    std::function
    /
    std::move_only_function
    /
    function_ref

    进行类型擦除
    double Optimizer(std::function<double>(double) f, double arg)
    {
        return f(arg);
    }
    

    并且,对于他们两个来说,那么

    double Calibrator::doThing()
    {
        return Optimizer([this](const double& d) {
            return this->testfunc(d);
        }, 10);
    }
    
© www.soinside.com 2019 - 2024. All rights reserved.