继承的显式模板可变参数构造函数是否影响类型默认可初始化性?C++20下d的判定
C++20中继承显式模板可变参数构造函数的默认可初始化性问题
问题1:继承的显式模板可变参数构造函数是否会影响一个类型的默认可初始化性?
问题2:根据C++20标准,d是否应被视为默认可初始化的?
代码示例
#include <concepts> struct b { explicit b(auto...) {} }; struct d : b {}; static_assert(std::default_initializable<d>); // clang不通过,gcc通过,msvc不通过
编译器错误信息
Clang错误信息
:5:15: 错误:静态断言失败 5 | static_assert(std::default_initializable ); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :5:15: 备注:因为'd'不满足'default_initializable' /gcc/include/concepts:160:6: 备注:因为'_Tp{}'非法: 所选构造函数在复制初始化中是显式的 160 | _Tp{}; | ^
MSVC错误信息
(5): 错误 C2607:静态断言失败 (5): 备注:概念'std::default_initializable '求值为false /msvc/include/concepts(100): 备注:'d':没有合适的默认构造函数可用 /msvc/include/concepts(100): 备注:非法的聚合初始化 /msvc/include/concepts(100): 备注:'b':没有合适的默认构造函数可用 /msvc/include/concepts(100): 备注:结构体'b'的构造函数被声明为'explicit'
问题解答
问题1的解答
继承的显式模板可变参数构造函数会影响派生类的默认可初始化性:
- 基类
b的explicit b(auto...)是模板构造函数,可匹配无参数调用(推导为空参数包)。 - 派生类
d未声明自己的构造函数,会继承基类的构造函数,且继承的构造函数保留explicit属性。 - 默认初始化
d(如d{})属于复制初始化语境,显式构造函数无法在此语境中被调用,导致初始化失败。
问题2的解答
根据C++20标准,d不应被视为默认可初始化的:
std::default_initializable要求类型能通过T{}或T()合法初始化。d{}需要调用基类的显式构造函数,但复制初始化语境不允许调用显式构造函数,因此该初始化非法。- 由于
d继承了基类的构造函数,编译器不会为d合成默认构造函数。而继承的显式构造函数无法满足默认初始化的要求,因此d不满足std::default_initializable概念。
GCC的通过属于实现错误,Clang和MSVC的行为符合标准规定。
内容的提问来源于stack exchange,提问作者303
相关产品推荐
相关产品推荐

