C ++ 11:std :: result_of<>模板参数vs std :: function<>

时间:2018-06-13 04:43:44

标签: c++ c++11 std-function result-of

我确实对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::declvalstd::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表达式?

感谢您即将进行的澄清!

2 个答案:

答案 0 :(得分:3)

Z(A,B,C)只是一种类型。这是一种功能类型。

您可以将类型传递给模板。模板对类型的作用取决于模板。

std::function<X>需要一个函数类型。它将其转换为operator()的签名。

std::result_of<X>需要一个函数类型。如果给定A(Ts...),则会计算使用()调用A类型的对象并使用参数Ts...的结果。

它在中被标记为被删除,因为函数类型有时会做有趣的事情(衰变参数,条带常量等)。现在invoke_result<F, Ts...>的行为与result_of<F(Ts...)>非常相似,只有几个角落差异。

结果总是滥用函数类型语法。但这里没有深刻的魔力;模板根据传入的类型执行任何他们想要的操作。

中,您可以通过模式匹配函数指针类型和检查&T::operator()获得有限的“result_of”功能。如果没有decltype / declval,编译器扩展或TR前标头,则无法在中获得所需的全部功能。

答案 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()案件需要更复杂的调度,否则 - 这是近似的方式。

相关问题