成员初始化无效的聚合类型,std::is_constructible应返回什么?
当聚合类型因成员字段的无效初始化无法创建对象时,std::is_constructible应返回什么?
示例代码
#include <type_traits> template <class T> struct A { T x{}; }; static_assert( !std::is_constructible_v<A<int&>> );
各编译器行为差异
A<int&> obj;是格式错误的代码,因为无法用{}初始化int&类型的非const左值引用。不同编译器的处理结果存在差异:
- GCC:符合预期,正常编译上述断言,判定
std::is_constructible_v<A<int&>>为false - MSVC:接受相反断言
static_assert( std::is_constructible_v<A<int&>> );,推测原因是未显式删除A的默认构造函数 - Clang:直接触发编译错误,错误信息如下:
error: non-const lvalue reference to type 'int' cannot bind to an initializer list temporary T x{}; ^~ : note: in instantiation of default member initializer 'A<int &>::x' requested here struct A { ^
标准规定的正确行为
根据C++标准,std::is_constructible_v<T>的判定逻辑是:类型T能否通过指定参数(此处无参数,即默认构造)完成合法初始化。
对于A<int&>,其默认初始化需要执行成员的默认初始化T x{};,但非const左值引用不支持值初始化({}属于值初始化语法),该初始化操作本身非法,意味着A<int&>无法被默认构造。按照标准,std::is_constructible_v<A<int&>>应当返回false。
综上,GCC的行为符合标准;Clang的报错是模板实例化阶段直接触发了初始化错误,并非对std::is_constructible的判定错误;MSVC的处理不符合标准要求。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

