无法使用默认参数初始化 lambda 成员变量

Cannot initialize a lambda member variable with a default argument

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

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参数不能?

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

如错误消息所述,您不能声明函数类型为 int(int) 的数据成员。

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

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

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_;
};