如果表达式的类型不依赖,应该怎么办,但我们用它来初始化静态自动变量? 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
,以便x
使用占位符类型,直到我们引用a.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似乎急切地实例化初始化程序以获得类型。但海湾合作委员会显然没有?我想了解发生了什么。
答案 0 :(得分:2)
除非已经显式实例化或明确专门化了类模板或成员模板的成员,否则在需要成员定义存在的上下文中引用特化时,将隐式实例化成员的特化;特别是,静态数据成员的初始化(以及任何相关的副作用)不会发生,除非静态数据成员本身的使用方式需要静态数据成员的定义。
简单地编写A<int> a;
不会以要求其定义存在的方式使用A<int>::x
,因此不应该进行初始化。 gcc是对的。