C++11:标准::result_of<>模板参数与标准::函数<>

C++11: std::result_of<> template argument vs std::function<>

本文关键字:gt lt 标准 参数 函数 C++11 result of      更新时间:2023-10-16

我确实对std::result_of<>做了一些研究,并且知道它是如何在高层次上使用的,但仍然对这个神奇的东西感到非常困惑。

因此,如果我理解正确,编译器应该将形式R (Args..)解释为采用类型Args...的参数并返回类型R的函数类型,并且在指定std::function<int(int)>时用法是非常合理的,它声明了一个以int作为其唯一参数的函数类型,并返回int

但是,当在std::result_of<F(Args...)>的上下文中使用相同的概念时,上述含义突然发生变化(请注意,我将R更改为F,并删除了(F(Args...)之间的(空格(以表示差异 - 根据cpp首选项,INVOKE的含义成为编译时std::result_of<F(Args...)>表达式 - 我的意思是, 我有点理解INVOKE的主要目的是使用decltype(std::declval<F>()(std::declval<Args>()...))的概念来选择正确的重载(如果存在多个重载(,当然还可以推断此类调用的返回类型(在编译时解析期间( - 实际上,这大致类似于:F (Args...)- 但是,与Args...情况相比,std::function<R (Args...)>的概念将被编译器解释为函数类型获取F并返回类型F,现在decltype是我们试图获取返回类型的函数类型!

当然,在std::declvalstd::result_of的帮助下,result_of的实施似乎是合理的,但我读到在 C++98/03 中以某种方式实现了 boostdecltype,其中不存在std::declvalR (Args...)- 我想知道这怎么可能(也许有一些非常黑客的技巧(?

所以重申一下:在作为模板参数的上下文中,R的概念是否总是被解释/推导为具有返回类型的函数类型std::function<>,无论封闭模板是std::result_of<>还是std::result_of<>? 虽然F以某种方式对"返回类型"进行了某种重新解释std::result_of<F(Args...)>::type, 并"返回"std::result_of<F(Args...)>定义的实际返回类型?或者F(Args...)只是以不同的方式解释INVOKE,所以它知道这是一个神奇的Z(A,B,C)表达?

感谢您即将发表的澄清!

std::function<X>只是一个类型。它是一种函数类型。

可以将类型传递给模板。 模板对类型执行的操作取决于模板。

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

A(Ts...)需要函数类型。 如果给定(),它会计算使用A调用带有参数invoke_result<F, Ts...>Ts...类型的对象的结果。

它在 c++17 中被标记为已弃用,因为函数类型有时会做一些有趣的事情(衰减参数、带状常量等(。 现在有result_of<F(Ts...)>的行为与result_of非常相似,但有一些极端情况差异。

&T::operator()始终是对函数类型语法的滥用。 但这里没有深奥的魔力;模板对传入的类型执行任何操作。

在 c++03 中,您可以通过模式匹配函数指针类型和检查decltype来获得有限的"result_of"功能。 如果没有 decltype/declval、编译器扩展或 TR pre-c++11 标头,就无法在 c++03 中获得所需的全部功能。

要在没有operator()的情况下实现它——好吧,一个简单的 carcass 老式实现,涵盖了很少的基本情况,可能是这样的

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

对于CC_53情况,需要更复杂的调度,但除此之外 - 这是大致的方法。