初始化器“sizeof(T)”内联静态自动...是否需要实例化? [英] Initializer "sizeof(T)" of inline static auto... Does it need instantiation?

查看:161
本文介绍了初始化器“sizeof(T)”内联静态自动...是否需要实例化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

A< int>一个;

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



它是否甚至必须根本解决 x 的类型?如果我没有记错的话,在C ++ 14以上版本中,语言允许使用占位符类型保留事物(如函数),并延迟实例化以便稍后查找实际的返回类型。它是否也必须将它应用于 x ,因此请使用占位符类型保留 x ,直到引用<$ c


$ b

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




编辑

有人问到

<

 模板< typename T>这是否等于这个? 
struct A {
static const std :: size_t x;
};

模板< typename T>
inline constexpr std :: size_t A< T> :: x = sizeof(T {}。f);


在我的问题中,我的问题中的静态数据成员是 auto 。因此,为了解 x 的类型,您需要知道初始化程序的类型。 Clang似乎为了获得类型而急切地实例化初始化程序。但GCC显然不是?我希望了解发生了什么。

$ b


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

简单地写 A< int> a; 不会使用 A< int> :: x ,因为它的定义是存在的,所以它的初始化不应该发生。 gcc是正确的。

What should happen if an expression's type is not dependent, but we use it to initialize a static auto variable? GCC and Clang differ in their behavior

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

A<int> a;

GCC doesn't raise an error. But Clang thinks that this is invalid because it instantiates the operand of "sizeof". GCC appears to skip that step because sizeof(T{}.f) always has type size_t (not type dependent), so it already knows type of x without instantiation. Both compilers conformly reject the program if we refer to x, for example by (void) a.x;.

Does it even have to resolve the type of x at all? With C++14 upwards the language allows keeping things (like functions) with a "placeholder type" and doing delayed instantiation to find out about the actual return type later on, if I remember correctly. Does it have to apply this to x aswell, so keeping x with a placeholder type till we refer to a.x?

What compiler is correct according to the Standards?


EDIT

Someone asked

uhm, shouldnt' this be equivalent to this ?

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);

The difference, and what concerns me in my question, is that the static data member in my question is auto. Therefore, in order to know the type of x, you need to know the type of the initializer. Clang appears to instantiate the initializer eagerly in order to get the type. But GCC doesn't, apparently? I would like to understand what's going on.

解决方案

From [temp.inst]/3:

Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.

Simply writing A<int> a; does noes not use A<int>::x in a way that requires its definition to exist, so its initialization should not occur. gcc is correct.

这篇关于初始化器“sizeof(T)”内联静态自动...是否需要实例化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆