函数的返回类型和它作为参数的类型应该相同
Should return type of a function and its type as argument be the same?
在这里我找到了这段代码(我已经修改了一点):
template<typename F>
void Eval( const F& f ) {
f(3.14);
}
据我所知,Eval函数接受另一个函数作为参数,并返回其参数的特定值(在上述情况下为3.14)。但是我不确定应该用什么作为函数的类型?它的返回类型?那么,应该这样称呼它吗?:
Eval<float>(sin)
此外,为什么要使用指针(&-symbol)呢?我们通过引用传递参数是因为我们想要改变它吗?我们要在Eval
函数中重新定义函数吗?如果是,为什么我们不这么做?如果不是,为什么我们需要&象征?
Eval
是一个函数模板。从这个模板实例化的函数有返回类型void
,这意味着它不返回值。它只是在内部调用f(3.14)
,然后返回给调用者。
其形参类型为,常量引用类型为F
,,其中F
为模板形参。通过const-reference传递意味着不能在函数内部修改对象,但是不进行复制。在函数内部,f
将只是传入的对象(或函数)的另一个名称。
Eval
显然希望它的参数是一个可调用类型:一个函数、一个指向函数的指针或一个定义了operator()
的类的对象。因此,不能将模板参数指定为double
。如果有的话,应该是double(double)
= function接受双精度体并返回双精度体。但是,大多数情况下,您根本不需要指定模板实参:它将从您传入的实际实参中推导出来。这样的:
void myFun(double x)
{
std::cout << x << 'n';
}
void someFun()
{
Eval(myFun);
Eval([](double a){ global_var = a; });
}
但是我不确定应该用什么作为函数的类型?
函数类型看起来像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);}
可以通过定义一个traits类,或者使用Boost的函数traits
来泛化这个那么,应该这样调用它吗?
如果只有一个函数具有该名称,则可以使用依赖参数的查找:
Eval(sin);
然而,如果这是std::sin
,那么就会有多个重载,所以你必须指定类型:
Eval<float(float)>(sin);
此外,为什么要使用指针(&-symbol)呢?
我们没有。那是引用,不是指针。
通过引用传递实参是因为我们想改变它吗?
。这是对const
的引用,所以我们不能改变它。
如果没有,为什么我们需要&象征?
有些类型的复制成本很高;有些是完全不能复制的;但是所有类型都可以通过引用传递。因此,一个完全泛型的函数模板需要通过引用来获取它的参数,以便对所有类型都可用。
你传递的是一个可调用类型,这意味着它要么是一个std::function<double(double)>
,要么是一个指向函数(double)(fooptr*)(double)
的函数指针,要么是一个类/结构体,它被doubule operator()(double)
重载,所以它可以像函数一样被调用。
在Eval
中有一个f()
的事实给了你任何传递给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);
}
实例
在c++中模板是在编译过程中实例化的,所以如果你传递任何支持调用的东西,它都会工作。
例如:class MyClass
{
public:
void operator() (double d)
{
// Do something
}
}
MyClass m;
Eval(m);
或:
Eval([](double d) { /* ... */ });
或:
void DoSth(double d)
{
// ...
}
Eval(DoSth);
为什么要传递const引用?原因如下:
- 传递的对象没有被复制,这提高了性能;
- 不能传递不存在的对象(引用不能为null)
- const在const引用中保证对象本身不会在函数调用中被改变
如果您想要返回值,您将希望使用如下内容
template<typename F>
typename F::result_type Eval(F f) {
return f(3.14);
}
指出- 按值传递函数更习惯。
- 这可能不适用于
void
返回类型。 - 功能必须具有适应性
- 你不需要传递模板参数,因为编译器可以自己计算。
据我所知,Eval函数将另一个函数作为参数并返回其值
No, Eval
返回void。没有使用任何f(3.14)
return。
但是我不确定应该用什么作为函数的类型?它的返回类型?那么,应该这样称呼它吗?:
Eval<float>(sin)
在大多数情况下,Eval(obj)
就足够了,F
类型将从obj
类型"推断"出来。如果这是模棱两可的,你需要明确:Eval<float(float)>(sin)
(我希望你包括正确的头文件)。任何可以用double
参数"调用"的类型的"对象"都将被编译。
Moreover, why do we use pointers (&-symbol)?
。这里的const
和&
表示const引用。您直接访问参数,但承诺不更改它。
- 在 c++ 中的模板实例化中使用带有构造函数的类作为类型参数
- 如何解决一元"*"(有"字符")错误的无效类型参数?
- "std::shared_ptr":不是参数"_Ty"的有效模板类型参数
- 具有可变参数非类型参数的模板专用化
- 函数类型参数的模板参数推导
- PowerShell 使用结构类型参数调用 C++ DLL 的导出函数
- 对于非常量指针类型的参数,未调用具有常量指针模板类型参数的功能
- 为模板传递非类型参数 agument
- 为什么带有类型参数的运算符 () 可以应用于 result_of 上下文中的类型?
- 使用其他模板类型参数作为要在函数签名中使用的类型别名声明
- 如何避免具有相同类型参数的函数中的错误
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- c++非类型参数包扩展
- 如何实现对参数顺序不可知的std::same_as的广义形式(即对于两个以上的类型参数)
- 在不同的模板参数包之间分发非类型参数包
- 如何在使用容器和字符串时强制使用显式分配器类型参数
- 错误:一元"*"的类型参数无效(具有"int"):使用 mergesort 计算
- EXPECT_CALL具有 unique_ptr 引用类型参数的模拟函数
- 作为模板类型参数,为什么 type[N] 与其专用版本不匹配----模板<类 T>类 S<T[]>
- C++ 模板:重载时找不到基类类型参数方法