首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何正确使用invoke_result_t?

如何正确使用invoke_result_t?
EN

Stack Overflow用户
提问于 2021-11-01 11:05:12
回答 2查看 300关注 0票数 0

我有一个类型的特点,我不明白的问题,我已经创建了以下最小的例子。为什么对foo的第二个调用不编译?它给出了错误:

代码语言:javascript
运行
复制
                 from C:/msys64/mingw64/include/c++/10.3.0/bits/nested_exception.h:40,
                 from C:/msys64/mingw64/include/c++/10.3.0/exception:148,
                 from C:/msys64/mingw64/include/c++/10.3.0/ios:39,
                 from C:/msys64/mingw64/include/c++/10.3.0/ostream:38,
                 from C:/msys64/mingw64/include/c++/10.3.0/iostream:39,
                 from invoke_result_test.cpp:1:
C:/msys64/mingw64/include/c++/10.3.0/type_traits: In substitution of 'template<class _Fn, class ... _Args> using invoke_result_t = typename std::invoke_result::type [with _Fn = main()::<lambda(bool&)>; _Args = {bool}]':
invoke_result_test.cpp:6:11:   required from here
C:/msys64/mingw64/include/c++/10.3.0/type_traits:2957:11: error: no type named 'type' in 'struct std::invoke_result<main()::<lambda(bool&)>, bool>'
 2957 |     using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;

在周围阅读时,该函数看起来是不可调用的,因此invoke_result没有type可返回。我希望能够用引用调用foo,这样我就可以返回值和非引用,但不能解决这个问题。这个是可能的吗?在STL代码管理这一点时,我假设是这样的。我还不明白什么?

最低限度守则:

代码语言:javascript
运行
复制
#include <type_traits>

template <typename F, 
          typename... A, 
          typename R = std::invoke_result_t<std::decay_t<F>, std::decay_t<A>...>>
R foo(const F& aF, const A& ...aA)

{
    return aF(aA...);
}

int main()
{
    bool positive = true;
    std::cout << foo([](bool flag) -> int
                        {
                            if (flag) return 1;
                            return -1;
                        },
                        positive);
                        
    std::cout << foo([](bool& flag) -> int
                        {
                            flag = !flag;
                            if (flag) return 1;
                            return -1;
                        },
                        positive);
                        
}

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-01 11:22:18

错误指示该函数不能用给定的参数调用。

std::invoke_result会自动将&&添加到参数类型,除非它们已经具有&。您的函数不能用bool &&参数调用。

即使忽略invoke_result,这也无法工作,因为foo通过const引用接收参数。

您需要对此类包装进行完美的转发:

代码语言:javascript
运行
复制
template <typename F, typename... A>
decltype(auto) foo(F &&f, A &&... a)
{
    return std::forward<F>(f)(std::forward<A>(a)...);
}

在这里,返回类型可以手动指定为std::invoke_result_t<F, A...>

但是,为了保持一致性,还应该将手动的f调用替换为std::invoke (以支持调用诸如指向成员的指针)。

代码语言:javascript
运行
复制
template <typename F, typename... A>
std::invoke_result_t<F, A...> foo(F &&f, A &&... a)
{
    return std::invoke(std::forward<F>(f), std::forward<A>(a)...);
}
票数 2
EN

Stack Overflow用户

发布于 2021-11-02 00:40:27

代码语言:javascript
运行
复制
template <typename F, 
      typename... A, 
      typename R = std::invoke_result_t<std::decay_t<F>, std::decay_t<A>...>>
R foo(const F& aF, const A& ...aA)

这会询问是否可以用F rvalue调用A rvalue。

你不能试试这个。你要尝试的是:

代码语言:javascript
运行
复制
      typename R = std::invoke_result_t<F const&, A const&...>>

如果进行此更改,代码现在为在第二种情况下,正确的编译失败,尝试用bool const&参数调用bool&参数。

如果您希望第二种情况也能工作,则不能将boolconst&获得,然后将其传递给期望有bool&的lambda。

代码语言:javascript
运行
复制
template <typename F, 
      typename... A, 
      typename R = std::invoke_result_t<F const&, A&&...>>
R foo(const F& aF, A&& ...aA)

{
  return aF(std::forward<A>(aA)...);
}

现在是这两个测试用例都编译

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69796012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档