使用包展开实现Lambda继承的FunctionSequence类编译报错问题
Lambda继承实现函数序列的编译错误排查
核心报错来源
- 继承访问权限缺失:C++中
class关键字定义的类型默认采用私有继承规则,写法class FunctionSequence : Ts...等价于对每个模板参数做私有继承,既无法顺畅完成基类子对象的外部初始化,也会导致基类成员的访问级别被压低。 - 缺少匹配参数包的构造函数:当前类仅自带编译器自动生成的拷贝、移动构造函数(均只接受1个同类型参数),没有定义能接收多个独立lambda对象的构造逻辑,因此编译器无法匹配
FunctionSequence{trimLeft, trimRight, capitalize}的3个入参初始化调用,直接报参数数量不匹配的错误,这也是当前编译输出中最直接的报错来源。 - 类内成员访问级别默认私有:所有没有显式指定访问限定符的类成员,都会默认进入private访问区,包括
using Ts::operator()...;引入声明和后续需要定义的构造函数。即便构造参数问题修复,后续调用trimAndCapitalize(str)时也会因为operator()是私有成员而触发访问权限报错。
可运行的修正方案
针对上述问题的调整点:
- 为继承列表显式添加
public访问限定符,替换默认的私有继承 - 新增public访问区,将
operator()引入声明和参数包构造函数放置在public区域,保证外部可访问、可初始化 - 补充修正原lambda中空字符串、全空格字符串场景的擦除逻辑,避免未定义行为
修正后的完整代码:
#include <iostream> #include <string> #include <cctype> template<class... Ts> class FunctionSequence : public Ts... { public: using Ts::operator()...; FunctionSequence(Ts... ts) : Ts(ts)... {} }; template <class...Ts> FunctionSequence(Ts...) -> FunctionSequence<Ts...>; int main(){ auto trimLeft = [](std::string& str) -> std::string& { auto pos = str.find_first_not_of(' '); if(pos != std::string::npos) str.erase(0, pos); return str; }; auto trimRight = [](std::string& str) -> std::string& { auto pos = str.find_last_not_of(' '); if(pos != std::string::npos) str.erase(pos+1); return str; }; auto capitalize = [](std::string& str) -> std::string& { for(auto& x : str) x = std::toupper(static_cast<unsigned char>(x)); return str; }; auto trimAndCapitalize = FunctionSequence{trimLeft, trimRight, capitalize}; std::string str = " what a Hullabaloo "; std::cout << "Before TrimAndCapitalize: str = \"" << str << "\"\n"; trimAndCapitalize(str); std::cout << "After TrimAndCapitalize: str = \"" << str << "\"\n"; return 0; }
程序运行输出
Before TrimAndCapitalize: str = " what a Hullabaloo " After TrimAndCapitalize: str = "WHAT A HULLABALOO"
内容的提问来源于stack exchange,提问作者getsoubl
相关产品推荐
相关产品推荐

