内联静态自动的初始值设定项"sizeof(T)"...它需要实例化吗?

Initializer "sizeof(T)" of inline static auto... Does it need instantiation?

本文关键字:sizeof 实例化 静态      更新时间:2023-10-16

如果表达式的类型不是依赖的,但我们使用它来初始化静态自动变量,会发生什么?GCC和Clang的行为不同

template<typename T>
struct A {
static inline auto x = sizeof(T{}.f);
};
A<int> a;

GCC不会引发错误。但是Clang认为这是无效的,因为它实例化了"sizeof"的操作数。GCC似乎跳过了这一步,因为sizeof(T{}.f)总是具有类型size_t(不依赖于类型),所以它在没有实例化的情况下就已经知道了x的类型。如果我们引用x,例如(void) a.x;,那么两个编译器都会一致地拒绝程序。

它甚至必须解决x的类型吗?在C++14以上版本中,如果我没记错的话,该语言允许将事物(如函数)保留为"占位符类型",并进行延迟实例化,以在以后找到实际的返回类型。它是否也必须将此应用于x,所以在我们引用a.x之前,保持x为占位符类型?

根据标准,什么编译器是正确的?


编辑

有人问

嗯,这不应该等同于这个吗?

template<typename T>
struct A {
static const std::size_t x;
};
template<typename T>
inline constexpr std::size_t A<T>::x = sizeof(T{}.f);

不同之处在于,我的问题中的静态数据成员是auto。因此,为了知道x的类型,您需要知道初始化器的类型。Clang似乎急切地实例化初始化器,以便获得类型。但海湾合作委员会显然没有?我想了解发生了什么。

来自[temp.inst]/3:

除非类模板或成员模板的成员已显式实例化或显式专门化,否则当在需要成员定义存在的上下文中引用专门化时,该成员的专门化将隐式实例化;特别是,静态数据成员的初始化(以及任何相关的副作用)不会发生,除非静态数据成员本身的使用方式需要静态数据成员定义的存在

简单地编写A<int> a;并不意味着不以需要其定义存在的方式使用A<int>::x,因此不应进行其初始化。gcc是正确的。