如何编写在C++中使用其他函数的函数
请考虑下面的代码,它包含在我制作的库中。如何编写在C++中使用其他函数的函数
#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
。有关说明,请参阅this answer。
有没有办法做一些像上面的模板代码,如果它的工作而不是诉诸于struct
小号包装besselJ
和besselH1
会做什么?我认为结构会增加不必要的复杂性。
更新:这个工程很漂亮,就像@aschepler建议它应该那样。实际代码中存在名称冲突。这花了额外的第1001次看看。我被其他*文章弄糊涂了,这些文章暗示这不起作用,因为函数指针是可变的。
的前提:
只要besselJ
在你的例子是功能的名称,而不是一个变量你正在使用的模板参数,然后通过一个函数指针作为非类型的模板参数应该工作。
查看live example。
替代解决方案:
如果你的函数指针在其值计算在运行时的变量举行,你将不会被允许使用该函数指针作为模板参数。如果你想使用一个运行时函数指针,你可以只使用一个普通功能参数,而不是一个模板参数:
#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);
}
更地道SOLUTION:(需要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 :: function',但在[文章](http://*.com/questions/9054774/difference-between-stdfunction-and-a-standard-function-pointer)比较'std :: function'和函数指针,除非需要额外的功耗,否则不鼓励使用'std :: function'。 – 2013-03-07 22:16:52
@JoeyDumont:决定是否使用'std :: function'主要是基于你的用例。 'std :: function'允许更多的灵活性(你可以传入一个lambda,一个函数,任何东西),它的“坏”性能(在大多数情况下是虚函数调用)只有在你证明它时才会成为问题成为瓶颈。否则,你应该关注干净的设计。这就是说,你不需要*使用'std :: function'。你可以使用常规函数指针,但是作为函数参数,而不是模板参数。 – 2013-03-07 22:20:04
@JoeyDumont:无论如何,正如我在答案的开头写的那样,只要你没有传入*变量*的值,模板参数也应该适用于你的情况。如果你是,也就是说,如果要在运行时确定要使用的函数,那么你几乎不得不使用函数参数而不是模板参数:是选择常规指针还是选择std :: function '取决于你。就我个人而言,我会去第二个。 – 2013-03-07 22:21:43
模板需要在编译时知道它们的参数。在运行时将模板参数拉出变量不起作用。
只需将函数指针作为函数参数即可。它不需要是模板功能。
std::complex<double> diffBessel(int order,
std::complex<double> z,
std::complex<double> (*T)(int, std::complex<double>))
确实,但这失败了,因为我有另一个函数,使用基地函数'diffBessel'。我需要一个可变数量的函数指针,而这绝对不是最好的。不过谢谢你的想法。 – 2013-03-07 22:11:28
链接的答案并不能解释为什么'diffbessel(args)'不起作用。据我所知,它应该工作。 –
aschepler
2013-03-07 21:47:00
你能显示GCC抱怨的确切代码吗? – Angew 2013-03-07 21:56:43
感谢你们俩。它**可以**工作。尽管我看了几个小时的代码,但我忽略了一个愚蠢的错误。 – 2013-03-07 22:12:46