为何std::is_constructible对平凡聚合类型不返回true?
回答
C++17模式下的判定完全符合标准
你觉得t{0}语法合法就应该让std::is_constructible<t, int>成立,本质是混淆了聚合初始化和类构造的判定边界:
- 你定义的
struct t是典型的聚合类型:没有用户声明构造函数、没有私有/保护非静态成员、没有虚函数。C++17中对聚合类型写t{0}走的是聚合初始化逻辑,本质是按声明顺序给成员依次赋值的语法糖,根本不会调用t的任何构造函数。 std::is_constructible的核心判定逻辑是检测T(Args...)形式的直接初始化是否良构。C17标准明确不允许用小括号对聚合做按成员的初始化,也就是说t(0)在C17下是编译错误,自然is_constructible会返回false,三个编译器的行为完全符合标准要求,不存在错误。
C++20模式下Clang的表现是特性未实现,不属于bug
C++20通过P0960R3提案修改了聚合初始化规则:
- 新标准允许用小括号传参初始化聚合类型,语义和同参数的花括号聚合初始化完全一致,对应的
std::is_constructible判定也同步覆盖了这种场景,按照标准要求std::is_constructible<t, int>在C++20下应当返回true。 - GCC、MSVC都已经在对应版本中实现了该提案,所以可以正常通过静态断言。
- Clang目前尚未完成P0960R3提案的开发落地,即使指定
-std=c++20编译参数也不会开启该特性,这属于编译器对新标准特性的实现滞后,不是逻辑错误类的bug,后续版本会逐步对齐标准要求。
测试用例代码如下:
#include <type_traits> struct t { int a; }; static_assert(std::is_constructible<t, int>{});
补充说明:即使在实现了P0960R3的编译器上,用int参数构造t的过程也不会生成隐式构造函数,t依然是平凡聚合类型,不会改变其内存布局和trivially copyable等属性。
内容的提问来源于stack exchange,提问作者303
相关产品推荐
相关产品推荐

