如何在c++中编写使用其他函数的函数

How to write functions that use other functions in C++

本文关键字:函数 其他 c++      更新时间:2023-10-16

考虑下面的代码,它包含在我制作的一个库中。

#include <complex>
std::complex<double> besselJ(int order, std::complex<double> z)
{
    // Function call
}
std::complex<double> besselH1(int order, std::complex<double> z)
{
   // Function call
}

注意两个函数有相同的签名。现在,我想写第三个函数不管它作用于besselJ还是besselH1都是一样的。我尝试了以下命令

template<std::complex<double> (*T)(int, std::complex<double>)>
std::complex<double> diffBessel(int order, std::complex<double> z)
{
    return T(order-1, z)-T(order+1,z);
}

当一个成员函数试图使用语法diffbessel<besselJ>(int, std::complex<double>时,GCC报错the value of 'besselJ' is not usable in a constant expression。请参阅这个答案以获得解释。

是否有一种方法可以像上面的模板代码那样做,如果它不诉诸于在struct s中包装besselJbesselH1 ?我认为结构体会增加不必要的复杂性。

更新:这工作得很漂亮,正如@aschepler建议的那样。实际代码中存在名称冲突。我多看了1001次才发现。我对其他StackOverflow文章感到困惑,这些文章建议这不会工作,因为函数指针是可变的。

前提:

如果besselJ在你的例子中是函数的名字,而不是你用作模板参数的变量的名字,那么传递一个函数指针作为非类型模板参数应该工作。

查看实例

替代解决方案:

如果函数指针保存在运行时计算其值的变量中,则不允许将该函数指针用作模板实参。如果想使用运行时函数指针,可以使用常规的函数参数,而不是模板参数:

#include <complex>
std::complex<double> diffBessel(
    std::complex<double> (*fxn)(int, std::complex<double>),
    int order,
    std::complex<double> z
    )
{
    return fxn(order-1, z) - fxn(order+1,z);
}

更习惯的解决方案:(需要c++ 11)

如果你想要更多的灵活性,c++ 11可以使用std::function<>:

#include <complex>
#include <functional>
std::complex<double> diffBessel(
    std::function<std::complex<double>(int, std::complex<double>)> fxn,
    int order,
    std::complex<double> z
    )
{
    return fxn(order-1, z)- fxn(order+1,z);
}

在这两种情况下,您的函数都可以这样调用:

int main()
{
    std::complex<double> c;
    /* ... */
    diffBessel(besselH1, 2, c);
}
进一步的可能性:

作为一种进一步的可能性,如果你不想或不能使用std::function<>,你可以让你的函数接受任何可调用的对象,使其成为一个模板:

template<typename F>
std::complex<double> diffBessel(
    F f,
    int order,
    std::complex<double> z
    )
{
    return f(order-1, z) - f(order+1,z);
}

同样,您将以与调用以前版本完全相同的方式调用它。

模板需要在编译时知道它们的参数。在运行时将模板参数从变量中取出是行不通的。

让函数指针成为函数形参。它不需要是模板函数。

std::complex<double> diffBessel(int order,
                                std::complex<double> z,
                                std::complex<double> (*T)(int, std::complex<double>))
相关文章: