您的版本不适用于例如指向成员。再仔细,但仍然没有确切的版本是:
template <class F, class... Args>
auto async(F&& f, Args&&... args)
-> future<decltype(ref(f)(forward<Args>(args)...))>;
与std::result_of
剩下的唯一的区别是,这个转发仿函数作为一个左值(一个问题,你的版本也万股)。换句话说,这种呼叫的结果(通过std::reference_wrapper<F>
)是typename std::result_of<F&(Args...)>::type
。
这是一个尴尬的局面,其中标准库的几个组成部分(仅举几例,除了那些我们刚刚见证:std::thread
,std::bind
,std::function
)在一个难以捉摸的援引术语规定(F, a0,a1,...,aN)伪表达式,它不完全等同于f(a0, a1, ... aN)
。由于std::result_of
是其中一个组件,并且实际上用于计算结果类型INVOKE,这就是您注意到的差异。
因为没有std::invoke
与std::result_of
类型特征串联,我认为后者仅用于描述例如当您的代码调用它们时,相关标准库组件的返回类型。如果你想要一个简洁而自我记录的写作方式,例如返回类型(一个非常有价值的目标是为了便于阅读,比喷灌decltype
无处不在),那么我建议你写你自己的别名:
template<typename F, typename... A>
using ResultOf = decltype(std::declval<F>()(std::declval<A>()...));
(如果你想别名被用作ResultOf<F(A...)>
代替ResultOf<F, A...>
那么你需要一些机器来模式匹配功能签名。)
这个别名的一个额外的好处是它是SFINAE友好的,不像std::result_of
。是的,这是它的另一个缺陷。 (公平地说,虽然已经对即将推出的标准进行了修改,但实施已经进行了相应的修改。)
如果您使用这样的特性,您可以使用指针,因为您可以修改指向成员的指针std::mem_fn
。
是否用'result_of'指定_或_implemented_?因为这可能只是实现它的家伙的心血来潮,或者它可能已经在'decltype'之前实现到目标编译器。在Apple的libC++中,它既不使用。 – zneak 2013-03-28 04:03:48
@zneak:我展示的声明被复制出标准,所以'std :: async'是通过'result_of'指定的。实现可以做任何他们喜欢的事情,只要它们提供的行为与指定的行为相同即可。 – KnowItAllWannabe 2013-03-28 06:03:03
只要知道'std :: result_of'语法有一些[不幸的含义](http://stackoverflow.com/a/15489789/500104)。 – Xeo 2013-03-28 07:44:15