我下面有程序:
#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中有一个类似的帖子,推论出我的函数类型failed。但这并不能说明为什么函子对象没问题,而函数却没问题。
(2)我不确定这是否与“ R call(F&f)”有关:函数类型不能声明l值吗?
(3)据我所知,任何带有名称的令牌(如变量/函数)都应视为l值。对于函数参数,编译器应将我的函数名称“ 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)据我所知,任何带有名称的令牌(如变量/函数)都应视为l值。对于函数参数,编译器应将我的函数名称“ f”“衰减”到函数指针,对吗?
不,请参见上面。您的call(F&)
函数通过引用来接受其参数,因此不会衰减。
(4)这就像衰减数组并将其传递给函数一样-函数指针可能是一个l值,那么“ call(F&f)”又是怎么回事呢?
当您通过引用传递数组时,它们也不会衰减。
如果你想在参数衰减,那么你应该写的call(F f)
不是call(F& f)
。但是,即使这样做,您仍然需要result_of
正确使用以得到f()
wheref
是左值的结果。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句