【问题标题】:Cannot initialize a lambda member variable with a default argument无法使用默认参数初始化 lambda 成员变量
【发布时间】:2022-01-07 16:57:21
【问题描述】:

我想用 c++17 编译下面的代码,这样我就可以传递任何具有特定签名 int(int) 的函数 (lambda),同时还允许使用默认参数:

template <class F = int(int)> // for deduction
struct A{
        A(F f = [] (int x){return x;}) : f_{f} {}

        F f_;
};

int main() {
        A work([](int x){return x + 1;});
        A not_work; // compile error.
}

但是,clang 会发出错误:

a.cpp:6:4: error: data member instantiated with function type 'int (int)'
        F f_;
          ^
a.cpp:11:4: note: in instantiation of template class 'A<int (int)>' requested here
        A not_work;
          ^

我不明白为什么我传递lambda时可以初始化成员f_而默认的lambda参数不能?

同时,有没有更好的方法来做到这一点?

【问题讨论】:

    标签: c++ templates lambda default-arguments


    【解决方案1】:

    正如错误消息所说,您不能声明具有 int(int) 之类的函数类型的数据成员。

    当传递一个lambda给构造函数时,模板参数F会被CTAD (since C++17)推导出为lambda闭包类型;当什么都不传递时F 将使用默认参数int(int) 并且数据成员f_ 的类型也将是int(int),这会导致错误。

    您可以使用函数指针类型(lambdas 没有捕获可以隐式转换为函数指针)或std::function&lt;int(int)&gt;。例如

    template <class F = int(*)(int)> // for deduction
    struct A{
            A(F f = [] (int x){return x;}) : f_{f} {}
    
            F f_;
    };
    

    或者

    template <class F = std::function<int(int)>> // for deduction
    struct A{
            A(F f = [] (int x){return x;}) : f_{f} {}
    
            F f_;
    };
    

    【讨论】:

    • 谢谢,但我还有一个问题。那么为什么A work([](int x){return x + 1;}); 行有效呢?在我看来,worknot_work 对象都将 lambda 作为其 ctor 中的参数,而其中只有一个有效。
    • @wk_j 因为当您将 lambda 传递给 A 的构造函数时,F 被推断为匿名 lambda 类型而不是 int(int),但是当您不提供参数时,默认值为使用int(int)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    • 2015-03-22
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    • 2015-06-21
    相关资源
    最近更新 更多