c++ - result_of<F(Args...> 和 decltype<f(args...)> 有什么区别?

标签 c++ c++11

我看到 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 适用于表达式。)

最佳答案

您的版本不适用于例如指向成员的指针。更接近但仍不准确的版本是:

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::threadstd::bindstd::function)以难以捉摸的形式指定INVOKE(f, a0, a1, ..., aN) 伪表达式,不完全等同于 f(a0, a1, ... aN) .从 std::result_of是这些组件之一,实际上用于计算 INVOKE 的结果类型,这就是您注意到的差异。

因为没有std::invokestd::result_of 一起出现类型特征我认为后者仅用于描述例如当您的代码调用它们时,相关标准库组件的返回类型。如果您想要一种简洁且 self 记录的写作方式,例如返回类型(对于可读性而言,这是一个非常有值(value)的目标,而不是到处撒 decltype),那么我建议您编写自己的别名:

template<typename F, typename... A>
using ResultOf = decltype( std::declval<F>()(std::declval<A>()...) );

(如果您希望将别名用作 ResultOf<F(A...)> 而不是 ResultOf<F, A...>,那么您需要一些机制来对函数签名进行模式匹配。)

std::result_of 不同,此别名的另一个好处是它对 SFINAE 友好。 .是的,这是它的另一个缺陷。 (公平地说,虽然这已经针对即将发布的标准进行了修改,并且实现已经在效仿。)

如果您使用这样的特性,您将不会丢失任何东西,因为您可以调整指向成员的指针,这要归功于 std::mem_fn .

关于c++ - result_of<F(Args...> 和 decltype<f(args...)> 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15673792/

相关文章:

c++ - OpenGL 固定点贴图故障

c++ - 为什么 std::shared_ptr 提供 operator<<?

c++ - 是否有 c++ 特性可以在 C++ 中的两种类型之间找到最受限制的类型?

c++ - 推导(非)模板类型的签名

c++ - std::invoke 没有匹配的重载函数发现 VS 2015 中给出的错误

c++ - 这个C++代码: "void Foo() throw;"?是什么意思

c++ - GJK碰撞检测从2D到3D的实现

c++ - 为 Windows cmd 添加 argc

c++ - 有没有办法使全局函数/静态成员函数可调用一次?

c++ - move 赋值运算符 C++