我有下面的程序:
#include<type_traits>
#include<iostream>
using namespace std;
template <class F, class R = typename result_of<F()>::type>
R call(F& f) { return f(); }
struct S {
double operator()(){return 0.0;}
};
int f(){return 1;}
int main()
{
S obj;
call(obj);//ok
call(f);//error!
return 0;
}
它无法在“call(f)”行中编译。
奇怪的是“call(obj)”是可以的。
(1) 我在另一个帖子 C++11 result_of deducing my function type failed 中有一个类似的帖子.但它并没有说明为什么仿函数对象可以,而函数则不行。
(2) 我不确定这是否与“R call(F& f)”有关:函数类型不能声明左值?
(3) 据我所知,任何具有名称的标记,如变量/函数,都应被视为左值。在函数参数的情况下,编译器应该将我的函数名“f”“衰减”为函数指针,对吗?
(4) 这就像衰减一个数组并将其传递给一个函数----而函数指针可能是一个l值,那么“call(F& f)”有什么问题?
您能否帮助进一步解释“为什么”是我的情况,我哪里出错了?
谢谢。
最佳答案
call(f)
的问题是你演绎的F
作为函数类型,因此它不会衰减为函数指针。相反,您会获得对函数的引用。然后是result_of<F()>
表达式无效,因为 F()
是 int()()
即返回函数的函数,该函数在 C++ 中不是有效类型(函数可以返回指向函数的指针,或对函数的引用,但不能返回函数)。
如果您使用 result_of<F&()>
它将起作用无论如何,这更准确,因为这就是您调用可调用对象的方式。内call(F& f)
你做f()
在这种情况下 f
是左值,所以你应该问调用左值的结果是什么 F
没有参数是,否则你可能会得到错误的答案。考虑:
struct S {
double operator()()& {return 0.0;}
void operator()()&& { }
};
现在
result_of<F()>::type
是 void
,这不是您想要的答案。如果您使用
result_of<F&()>
那么你就得到了正确的答案,它也适用于 F
是函数类型,所以 call(f)
也有效。(3) As long as I know, any token with a name, like variable/function, should be considered a l-value. And in the case of function parameter, compiler should "decay" my function name "f" to a function pointer, right?
不,见上文。您的
call(F&)
函数通过引用获取其参数,因此没有衰减。(4) This is like decaying an array and pass it to a function----And a function pointer could be an l-value, then what's wrong with "call(F& f)"?
当您通过引用传递数组时,数组也不会衰减。
如果你想让参数衰减,那么你应该写
call(F f)
不是 call(F& f)
.但即使你这样做,你仍然需要使用 result_of
正确获得 f()
的结果哪里f
是一个左值。
关于function - C++11:为什么 result_of 可以接受仿函数类型作为 lvalue_reference,但不能接受函数类型作为 lvalue_reference?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38118563/