4

我有下面的程序:

#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) 这就像衰减一个数组并将其传递给一个函数----并且函数指针可以是一个左值,那么“调用(F&f)”有什么问题?

您能否就“为什么”是我的情况提供进一步的解释,我在哪里做错了?谢谢。

4

1 回答 1

5

问题call(f)在于您推断F为函数类型,因此它不会衰减为函数指针。相反,您会获得对函数的引用。那么result_of<F()>表达式是无效的,因为ieF()int()()一个返回函数的函数,它在 C++ 中不是有效类型(函数可以返回指向函数的指针,或对函数的引用,但不能返回函数)。

如果您使用哪个更准确,它将起作用result_of<F&()>,因为这就是您调用可调用对象的方式。在call(F& f)你的内部,f()并且在那个上下文中f是一个左值,所以你应该问一下调用不F带参数的左值的结果是什么,否则你可能会得到错误的答案。考虑:

struct S {
  double operator()()& {return 0.0;}
  void operator()()&& { }
};

现在result_of<F()>::typevoid,这不是您想要的答案。

如果您使用result_of<F&()>,那么您会得到正确的答案,并且它也适用于F函数类型,因此call(f)也适用。

(3) 据我所知,任何有名字的记号,比如变量/函数,都应该被认为是左值。在函数参数的情况下,编译器应该将我的函数名“f”“衰减”为函数指针,对吧?

不,见上文。您call(F&)的函数通过引用获取其参数,因此没有衰减。

(4) 这就像衰减一个数组并将其传递给一个函数----并且函数指针可以是一个左值,那么“调用(F&f)”有什么问题?

当您通过引用传递数组时,数组也不会衰减。

如果您希望参数衰减,那么您应该写call(F f)not call(F& f)。但即使你这样做了,你仍然需要result_of正确使用来获得f()where fis an lvalue 的结果。

于 2016-06-30T09:10:47.983 回答