You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确使用std::invoke_result_t?接收引用参数的lambda传入模板编译失败

错误原因

你代码的问题出在std::invoke_result的参数传递逻辑和foo函数的参数转发逻辑两处:

  1. std::invoke_result_t<Fn, Args...>中的Args...需要对应实际传入函数的参数的类型和值类别,你给参数加了std::decay_t会剥离所有引用、cv限定符,直接把类型退化为值类型。对于第二个要求bool&(非常量左值引用)入参的lambda,invoke_result会判定你要给它传入一个纯右值bool,而纯右值无法绑定到非常量左值引用,自然不存在type成员,触发编译报错。
  2. 你定义的foo函数形参是const A& ...aA,传递给lambda的参数是常量左值引用,也无法绑定到第二个lambda要求的非const左值引用,哪怕改对invoke_result的写法,调用阶段也会报错。
修复方案

你需要使用万能引用+完美转发实现类似STL的参数传递逻辑,同时去掉std::decay_t对参数类型的错误处理,修改后的代码如下:

#include <type_traits>
#include <iostream>
#include <utility>

template <typename F, typename... A>
std::invoke_result_t<F&&, A&&...> foo(F&& aF, A&& ...aA)
{
    return std::forward<F>(aF)(std::forward<A>(aA)...);
}

int main()
{
    bool positive = true;
    std::cout << foo([](bool flag) -> int
                        {
                            return flag ? 1 : -1;
                        },
                        positive) << '\n';
                        
    std::cout << foo([](bool& flag) -> int
                        {
                            flag = !flag;
                            return flag ? 1 : -1;
                        },
                        positive) << '\n';
    // 可验证传入的positive已经被lambda修改
    std::cout << std::boolalpha << positive << '\n';
    return 0;
}
修改说明
  • 函数对象和参数都使用万能引用T&&声明,配合std::forward可以完美保留参数的原值类别、cv限定符和引用属性,不管是值类型、左值引用、右值引用、常量/非常量参数都可以正确传递。
  • 直接把转发后的参数类型传递给std::invoke_result,保证类型判定和实际调用逻辑完全一致,同时兼容引用传参和值传参的场景。

内容的提问来源于stack exchange,提问作者GrumpyBloke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 11:06:00