Here我找到了这部分代码(我稍微修改了一下):
template<typename F>
void Eval( const F& f ) {
f(3.14);
}
据我所知,Eval函数将另一个函数作为参数,并为其参数的特定值返回其值(在上述情况下为3.14)。但我不确定应该使用什么作为函数的类型?它的返回类型?那么,是否应该按以下方式调用?:
Eval<float>(sin)
此外,为什么我们使用指针(&amp; -symbol)?我们是否通过参考传递参数,因为我们想改变它?我们是否要在Eval
函数内重新定义函数?如果是的话,为什么我们不这样做呢?如果没有,为什么我们这样做,我们需要&amp;符号
答案 0 :(得分:3)
Eval
是一个功能模板。从此模板实例化的函数具有返回类型void
,这意味着它不返回值。它只是在内部调用f(3.14)
然后返回调用者。
其参数类型为类型F
的常量引用,其中F
是模板参数。通过const-reference传递意味着你不能修改函数内部的对象,但没有复制。函数f
内部只是对象(或函数)的不同名称传入。
Eval
显然希望它的参数是一个可调用类型:一个函数,一个指向函数的指针或一个定义operator()
的类的对象。因此,您无法将模板参数指定为double
。如果有的话,它应该是double(double)
=函数取一个double并返回一个double。但是,大多数情况下,您根本不必指定模板参数:它将从您传入的实际参数中推断出来。就像这样:
void myFun(double x)
{
std::cout << x << '\n';
}
void someFun()
{
Eval(myFun);
Eval([](double a){ global_var = a; });
}
答案 1 :(得分:2)
但我不确定应该使用什么作为函数的类型?
函数类型看起来像float(float)
。
或者你的意思是回归类型?在现代C ++中,您可以推断出返回类型:
template <typename F>
auto Eval(const F & f) -> decltype(f(3.14)) {
return f(3.14);
}
如果你坚持使用旧版本的语言,那就相当棘手了。您可以为普通函数以及包含result_type
定义的函数类型(例如从std::unary_function
派生的函数类型)提供重载:
template <typename Ret, typename Arg>
Ret eval(Ret (&f)(Arg)) {return f(3.14);}
template <typename F>
typename F::result_type eval(F const & f) {return f(3.14);}
可能通过定义特征类或使用Boost's function traits
来概括这一点那么,是否应该按以下方式调用?
如果只有一个具有该名称的函数,则可以使用依赖于参数的查找:
Eval(sin);
但是,如果这是std::sin
,那么有多个重载,因此您必须指定类型:
Eval<float(float)>(sin);
此外,为什么我们使用指针(&amp; -symbol)?
我们没有。这是一个参考,而不是一个指针。
我们是否通过引用传递参数,因为我们想要改变它?
没有。它是对const
的引用,因此我们无法更改它。
如果没有,我们为什么要这样做&amp;符号
某些类型的复制费用昂贵;其他人根本无法复制;但所有类型都可以通过引用传递。因此,完全通用的函数模板需要通过引用获取其参数,以便可用于所有类型。
答案 2 :(得分:1)
你传递的是可调用类型,这意味着它是std::function<double(double)>
或指向函数(double)(fooptr*)(double)
或类/结构的函数指针其中doubule operator()(double)
重载,以便可以像调用它一样调用它。
您f()
中有Eval
的事实告诉您,传递给F
的任何类型都应该使用()
来调用
以下是您可以使用它的示例:
#include<iostream>
template<typename F>
void Eval( const F& f ) {
std::cout << f(3.14);
}
double foo(double d)
{
return d + d;
}
int main()
{
Eval(foo);
}
答案 3 :(得分:0)
在C ++模板中,在编译过程中实例化,所以如果你传递任何支持调用的东西,它都会有效。
例如:
class MyClass
{
public:
void operator() (double d)
{
// Do something
}
}
MyClass m;
Eval(m);
或者:
Eval([](double d) { /* ... */ });
或者:
void DoSth(double d)
{
// ...
}
Eval(DoSth);
为什么我们传递const引用?有几个原因:
答案 4 :(得分:0)
如果您想要返回该值,您可能希望使用类似这样的内容
template<typename F>
typename F::result_type Eval(F f) {
return f(3.14);
}
void
返回类型。答案 5 :(得分:0)
据我所知,Eval函数需要另外一个函数 参数并返回其值
不,Eval
返回无效。无论使用何种f(3.14)
返回。
但是我不确定应该使用什么作为函数的类型?它的 返回类型?那么,是否应该按以下方式调用?:
Eval<float>(sin)
在大多数情况下,Eval(obj)
就足够了,F
类型将从obj
类型“推断”出来。如果是ambiguos,你需要明确:Eval<float(float)>(sin)
(我已经包含了rigth头文件)。可以使用double
参数“调用”的任何类型的“对象”都将编译。
Moreover, why do we use pointers (&-symbol)?
没有。这里const
和&
表示const引用。您可以直接访问参数,但保证不会更改它。