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

为何无法给Lambda函数参数加默认值?求替代实现方案

解决Lambda作为函数默认参数且带decay默认值的问题

问题背景

在实现EMA权重更新方法时,希望将Lambda作为函数的默认参数,同时给decay设置默认值(如0.999),但在MSVC下遇到error C2383: 'updwp': default-arguments are not allowed on this symbol报错——C++标准不允许在函数指针/引用类型的参数中声明默认参数,直接给Lambda参数加默认值、用std::bind结合std::function的尝试均失效。

可行解决方案

方案1:将decay设为独立默认参数

把decay提取为函数顶层参数并设置默认值,默认Lambda仅接收参数不声明默认值,调用时传递默认decay即可。这种方式既规避了函数指针的默认参数限制,又保留了decay的可配置性。

#include <torch/torch.h>

void ema_update(int i, const NetImpl& mdl, 
                double decay = 0.999,
                // 默认Lambda不声明decay的默认值,仅接收传入的参数
                void (*updwp)(torch::Tensor&, const torch::Tensor&, double) = [](torch::Tensor& w, const torch::Tensor& w1, double decay) {
                    w.set_data(w.data().detach() * decay + w1.detach() * (1. - decay));
                },
                void (*updw)(torch::Tensor&, const torch::Tensor&, double) = [](torch::Tensor& w, const torch::Tensor& w1, double decay) {
                    w = w.detach() * decay;
                    w += w1.detach() * (1. - decay);
                }) {
    // 权重更新逻辑示例:遍历模型参数调用更新函数
    for (auto& [name, param] : mdl.named_parameters()) {
        torch::Tensor w_ema = /* 对应EMA权重张量 */;
        updwp(w_ema, param, decay);
    }
}

简化测试示例:

void f(double b = 0.77, void (*pf)(int&, double) = [](int& a, double b) {
    a *= b;
}) {
    int a = 9;
    pf(a, b); // 传递默认或自定义的b值
}

方案2:Lambda内部捕获/定义默认decay

如果decay的默认值无需外部修改,可以直接在默认Lambda内部固定decay值,此时函数指针的参数列表无需包含decay,彻底避免默认参数冲突。

#include <torch/torch.h>

void ema_update(int i, const NetImpl& mdl, 
                void (*updwp)(torch::Tensor&, const torch::Tensor&) = [](torch::Tensor& w, const torch::Tensor& w1) {
                    const double decay = 0.999; // 内部固定默认值
                    w.set_data(w.data().detach() * decay + w1.detach() * (1. - decay));
                },
                void (*updw)(torch::Tensor&, const torch::Tensor&) = [](torch::Tensor& w, const torch::Tensor& w1) {
                    const double decay = 0.999;
                    w = w.detach() * decay;
                    w += w1.detach() * (1. - decay);
                }) {
    // 权重更新逻辑示例
    for (auto& [name, param] : mdl.named_parameters()) {
        torch::Tensor w_ema = /* 对应EMA权重张量 */;
        updwp(w_ema, param); // 无需传递decay
    }
}

简化测试示例:

void f(void (*pf)(int&) = [](int& a) {
    const double b = 0.77; // 内部固定默认值
    a *= b;
}) {
    int a = 9;
    pf(a);
}

修复std::function + std::bind的写法

之前的std::bind失败是因为参数顺序和占位符使用错误,调整后即可正常工作:

#include <functional>
void f3(double b = 0.77, std::function<void(double, int&)> fa = [](double b, int& a) {
    a *= b;
}) {
    int a = 9;
    // 用占位符标记后续传入的int&参数
    auto f = std::bind(fa, b, std::placeholders::_1);
    f(a);
}

失败原因说明

  1. C++标准禁止在函数指针/引用类型的参数中声明默认参数,因此void (&updwp)(..., double decay = 0.999)属于非法语法,MSVC严格执行了这一规则。
  2. 最初的std::bind尝试未使用占位符,导致参数绑定顺序错误,无法匹配Lambda的参数列表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:03:12