gpt4 book ai didi

c++ - 关于获取函数结果类型的各种方法

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:18:12 25 4
gpt4 key购买 nike

在必须推导函数调用结果类型的上下文中,C++ 似乎更乐于帮助我们,提供(至少据我所知是以下)两种解决方案:

  • result of类型特征:

    std::result_of<F(Args...)>::type
  • 核心语言语法:

    decltype(std::declval<F>()(std::declval<Args>()...); 

我的问题是,两者之间有什么区别吗?是否存在一个不能被另一个替代的上下文,如果不是,为什么我们需要一个类型特征来做一些语言可以开箱即用的事情?

最佳答案

存在三个差异。

  1. 最初,std::result_of不需要对 SFINAE 友好。因此,如果要在上下文中使用它来验证 F可以用 Args... 调用,它会给你一个硬错误,而 decltypestd::declval只会导致可能的预期替代失败。 N3462修复了规范,使其对 SFINAE 友好。

    虽然在兼容的 C++14 编译器上,两者都是 SFINAE 友好的。 std::result_of_t<Fn(ArgsTypes...)>实际上是根据后者定义的。来自 [meta.trans.other]:

    If the expression INVOKE (declval<Fn>(), declval<ArgTypes>()...) is well formed when treated as an unevaluated operand (Clause 5), the member typedef type shall name the type decltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...)); otherwise, there shall be no member type.

  2. 正如result_of的语言定义所明确的那样, 类型 Fn可以是任何东西INVOKE -able,而显式调用std::declval<F>()仅适用于函数和函数对象。所以如果你有:

    using F = decltype(&X::bar);
    using T1 = std::result_of_t<F(X*)>; // ok
    using T2 = decltype(std::declval<F>()(std::declval<X*>()); // not ok
  3. 对于某些类型,std::result_of由于指定某些 type-id 是非法的(参见 my related question ),因此实际上不起作用。这些类型正在使用 F 的函数(与函数的指针/引用相反)或对任何 Args... 使用抽象类.因此,考虑一些看似无害的事情:

    template <class F, class R = std::result_of_t<F()>>
    R call(F& f) { return f(); }

    int foo();
    call(foo); // error, unresolved overload etc.

    这会导致 SFINAE 失败(至少这不是硬错误),因为我们必须形成类型 int()() - 返回函数的空函数。现在,从技术上讲,我们错误地编写了代码。应该是:

    template <class F, class R = std::result_of_t<F&()>>
    R call_fixed(F& f) { return f(); }

    这行得通。但是如果我们在 declval 上犯了同样的错误,我们会没事的:

    template <class F, class R = decltype(std::declval<F>()())>
    R call_declval(F& f) { return f(); }

关于c++ - 关于获取函数结果类型的各种方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35834026/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com