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()>::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
是一个左值。
我有以下程序:
#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) 我在另一个帖子
(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()>::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
是一个左值。