我确实对std::result_of<>
进行了一些研究,并且知道它是如何在高级别上使用的,但我仍然对这个神奇的东西感到困惑。
所以,如果我理解正确的话,编译器{@ 1}}应该被解释为一个函数类型,它接受类型R (Args..)
的参数并返回类型Args...
,以及用法在指定R
时非常合理,它声明了一个以std::function<int(int)>
为唯一参数的函数类型,并返回int
。
但是,当int
的上下文中使用相同的概念时,上述含义会突然改变(请注意,我已将std::result_of<F(Args...)>
更改为R
,并删除了{{1 ({1}}和F
之间的(空格)表示差异 - 根据cppreference,的含义变成编译时
F
表达式 - 我的意思是,我很亲切理解(
的主要目的是使用F(Args...)
的概念来选择正确的重载(如果存在多个重载),当然还要推断出这种调用的返回类型(在此期间)编译时间分辨率) - 实际上,这大致类似于:INVOKE
- 然而,std::result_of<F(Args...)>
的概念 - 与INVOKE
情况相比 - 将被编译器解释为函数类型取decltype(std::declval<F>()(std::declval<Args>()...))
并返回类型F (Args...)
,现在std::function<R (Args...)>
是我们尝试获取返回类型的函数类型!
当然,在Args...
和F
的帮助下,F
的实现似乎是合理的,但我读到了在C ++ 98中以某种方式实现decltype
的提升/ 03其中std::declval
和std::result_of
不存在 - 我想知道这怎么可能(也许有一些非常黑客的伎俩)?
所以要重新迭代:作为模板参数的上下文中result_of
的概念总是被解释/推导为具有返回类型decltype
的函数类型,无论封闭模板是std::declval
还是R (Args...)
?而R
以某种方式对“返回类型”std::function<>
进行某种重新解释,并“返回”由std::result_of<>
定义的实际返回类型?或者std::result_of<>
只是以不同的方式解释F
,所以它知道这是一个神奇的std::result_of<F(Args...)>::type
表达式?
感谢您即将进行的澄清!
答案 0 :(得分:3)
Z(A,B,C)
只是一种类型。这是一种功能类型。
您可以将类型传递给模板。模板对类型的作用取决于模板。
std::function<X>
需要一个函数类型。它将其转换为operator()
的签名。
std::result_of<X>
需要一个函数类型。如果给定A(Ts...)
,则会计算使用()
调用A
类型的对象并使用参数Ts...
的结果。
它在c++17中被标记为被删除,因为函数类型有时会做有趣的事情(衰变参数,条带常量等)。现在invoke_result<F, Ts...>
的行为与result_of<F(Ts...)>
非常相似,只有几个角落差异。
结果总是滥用函数类型语法。但这里没有深刻的魔力;模板根据传入的类型执行任何他们想要的操作。
在c++03中,您可以通过模式匹配函数指针类型和检查&T::operator()
获得有限的“result_of”功能。如果没有decltype / declval,编译器扩展或TR前c++03标头,则无法在c++11中获得所需的全部功能。
答案 1 :(得分:1)
在没有decltype
的情况下实现它 - 好吧,一个简单的尸体oldschool实现,涵盖了几个基本情况可能会像
template<class F> struct MemberRetVal;
template<class C,typename R> struct MemberRetVal<R (C::*)()> {
using type = R;
};
template<class C,typename R> struct MemberRetVal<R (C::*)() const> {
using type = R;
};
template<class C,typename R, typename A1> struct MemberRetVal<R (C::*)(A1)> {
using type = R;
};
template<class C,typename R, typename A1> struct MemberRetVal<R (C::*)(A1) const> {
using type = R;
};
// ...
// A few more member function arities
// ...
template<typename F> struct ResultOf;
template<typename F> struct ResultOf<F (*)()> {
using type = typename MemberRetVal<&F::operator()>::type;
};
template<typename R> struct ResultOf<(R (*)())(*)()> {
using type = R;
};
template<typename F, typename A1> struct ResultOf<F (*)(A1)> {
using type = typename MemberRetVal<&F::operator()>::type;
};
template<typename R, typename A1> struct ResultOf<(R (*)(A1))(*)(A1)> {
using type = R;
};
// and so forth
operator()
案件需要更复杂的调度,否则 - 这是近似的方式。