C++11:为什么 result_of 可以接受函子类型 lvalue_reference,但不能接受函数类型 lvalue_reference?

C++11: Why result_of can accept functor type as lvalue_reference, but not function type as lvalue_reference?

我有以下程序:

#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) 我在另一个帖子 中有一个类似的 post。但它并没有说明为什么仿函数对象可以而函数却不行。

(2)我不确定这是否与"R call(F& f)"有关:函数类型不能声明左值?

(3) 据我所知,任何带有名称的标记,如 variable/function,都应被视为左值。在函数参数的情况下,编译器应该 "decay" 我的函数名 "f" 到函数指针,对吗?

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

能不能帮忙解释一下"why"是我的情况,我哪里错了? 谢谢。

call(f) 的问题在于您将 F 推断为函数类型,因此它不会退化为函数指针。相反,你得到一个函数的引用。然后 result_of<F()> 表达式无效,因为 F()int()() 即 return 函数的函数,这在 C++ 中不是有效类型(函数可以 return 指向函数的指针,或对函数的引用,但不是函数)。

如果您使用更准确的 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) 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 是一个左值。