C++类中用auto声明lambda函数及set自定义排序报错如何解决?
结论先行
可以在C类中使用auto声明lambda作为成员,只需要符合C语法对静态成员初始化的相关要求即可。
报错原因说明
- 第一个类内初始化lambda静态成员报错的原因:C++标准规定,仅整型、枚举类型的
const静态成员支持直接在类内初始化,其他类型的const静态成员如果要在类内赋值,必须添加constexpr修饰符。lambda对应的闭包类型不属于标准允许类内初始化的const静态整型范畴,因此不加constexpr会触发编译错误。 - 第二个lambda移到类外后
unknown type name 'cmp'报错的原因:类内声明set<int, decltype(cmp) >时,需要cmp的定义在类定义之前可见,若cmp的定义位置晚于类定义,编译器无法解析decltype(cmp)对应的类型,就会抛出类型未找到的错误。
另外原有代码还存在隐藏问题:类内声明成员变量sortedSet(cmp)用括号初始化,会被C++语法解析为「返回set类型、名为sortedSet的成员函数声明」,而非成员变量初始化,这也会触发编译错误。
修复方案
方案1:C++17及以上版本(推荐,逻辑最简洁)
直接给静态lambda成员加constexpr修饰,成员变量初始化改用花括号避免函数声明歧义,代码示例:
#include <set> class Temp { public: // 加constexpr允许类内初始化静态lambda成员 static constexpr auto cmp = [](int p1, int p2) { return p1>p2; }; // 用花括号初始化成员变量,避免解析为函数声明 std::set<int, decltype(cmp) > sortedSet{cmp}; Temp() { } };
方案2:兼容C++11/14版本
将静态lambda成员的声明和类外初始化拆分,在构造函数初始化列表中初始化set:
#include <set> class Temp { public: // 类内仅声明静态cmp成员 static const auto cmp; // 只声明set成员,不做初始化 std::set<int, decltype(cmp) > sortedSet; Temp() : sortedSet(cmp) { // 构造函数初始化列表传入cmp实例 } }; // 类外定义cmp const auto Temp::cmp = [](int p1, int p2) { return p1>p2; };
内容的提问来源于stack exchange,提问作者flexter
相关产品推荐
相关产品推荐

