C++可变参数继承场景为何需要转发构造参数初始化基类
问题解答
问题1:修改后的程序是否符合C++标准,属于良构程序?
修改后的程序不属于通用的C++标准良构程序,MSVC开启C++20后的编译通过属于特定场景下的实现兼容,不代表代码符合标准设计要求:
- 在C++17及更早标准下,程序完全非良构:所有lambda类型都不提供默认构造函数,派生类
OverloadSet的构造函数没有在初始化列表显式初始化基类,编译器尝试调用基类默认构造函数时必然失败,GCC和Clang的报错完全符合标准要求。 - 在C20及更高标准下,仅当传入的所有lambda都是无捕获类型时,程序才满足良构条件:C20仅放开了无捕获lambda的默认构造限制,如果lambda带捕获,仍然没有默认构造函数,编译必然失败。且这种写法完全丢弃了传入的lambda实例,和重载集的通用设计意图相悖。
问题2:仅使用基类的operator(),为何仍需要转发参数完成基类初始化?
这是C++对象模型的硬性要求:
- 任何类实例在使用前必须完成完整的构造流程,派生类构造时必须初始化所有直接基类,这个规则和你后续是否会用到基类的成员变量无关。
- 虽然无捕获lambda的
operator()确实不依赖对象的存储状态,但标准没有允许跳过基类的构造步骤。 - 原始实现的转发构造逻辑具备通用性:可以兼容所有lambda类型,无论是否带捕获、无论使用哪个版本的C++标准,都可以正常完成基类构造,不会限制重载集的使用场景。
内容的提问来源于stack exchange,提问作者Eduard Rostomyan
相关产品推荐
相关产品推荐

