我看到std::async
指定如下:
template <class F, class... Args> // copied out of the standard
future<typename result_of<F(Args...)>::type>
async(F&& f, Args&&... args);
我曾预料到它会被声明为:
template <class F, class... Args>
auto async(F&& f, Args&&... args) ->
future<decltype(forward<F>(f)(forward<Args>(args)...)>;
这是相同的,还是某种方式使用result_of
比使用decltype
更好? (我了解result_of
适用于类型,而decltype
适用于表达式。)
答案 0 :(得分:11)
您的版本不适用于,例如指向成员的指针。更接近但仍然不准确的版本是:
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
)根据难以捉摸的 INVOKE(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
调整指向成员的指针。
答案 1 :(得分:5)
从功能的角度来看,没有任何区别。但是,decltype
版本使用 trailing-return-type ,这与编程的观点有一点不同。
在C ++ 11中,std::result_of
并非绝对必要,可以使用decltype
代替,就像你使用的方式一样。但是std::result_of
向后兼容第三方库(较旧的库),例如具有result_of
的Boost。但是,我没有看到太多的优势。
就我个人而言,我更喜欢使用decltype
,因为它更强大并适用于任何实体,而result_of
仅适用于可调用实体。因此,如果我使用decltype
,我可以随处使用它。但是对于result_of
,我偶尔会切换到decltype
(也就是说,当实体不可调用时)。请参阅我在所有函数的返回类型中使用decltype
的{{3}}。
答案 2 :(得分:5)
您的问题已经存在差异:“我了解result_of
适用于类型,而decltype
适用于表达式。”
它们都提供相同的功能(std::result_of
甚至实现了decltype
现在而且您的示例的差异几乎不存在,因为您已经有必要的变量来构建表达式。
也就是说,当你只有类型时,差异归结为语法糖。考虑:
typename std::result_of< F( A, B, C ) >::type
VS
decltype( std::declval<F>()( std::declval<A>(), std::declval<B>(), std::declval<C>() )
请记住std::result_of
在这些情况下是一种选择。
请注意,还有一些情况decltype
可以std::result_of
无法使用。考虑decltype( a + b )
,据我所知,您无法找到F
来创建等效的std::result_of< F( A, B ) >
。