为什么' std::initializer_list '没有定义为文字类型?

时间:2021-02-27 22:45:04

This is a follow-up of this question: Is it legal to declare a constexpr initializer_list object?.

这是这个问题的后续:声明constexpr initializer_list对象是否合法?

Since C++14, the std::initializer_list class has all of its methods marked with constexpr. It seems natural to be able to initialize an instance by doing constexpr std::initializer_list<int> list = {1, 2, 3}; but Clang 3.5 complains about list not being initialized by a constant expression. As dyp pointed out in a comment, any requirement for std::initializer_list to be a literal type seem to have vanished from the specs.

自c++ 14以来,std::initializer_list类的所有方法都用constexpr标记。通过执行constexpr std::initializer_list list ={1,2,3}来初始化一个实例似乎很自然;但是Clang 3.5抱怨列表没有被常量表达式初始化。正如dyp在一篇评论中指出的,任何对std::initializer_list是文字类型的要求似乎都从规范中消失了。

What's the point of having a class fully defined as constexpr if we can't even initialize it as such? Is it an oversight in the standard and will get fixed in the future?

如果我们甚至不能初始化一个完全定义为constexpr的类,有什么意义呢?这是标准中的一个疏忽,将来会得到修正吗?

1 个解决方案

#1


5  

The standard committee seems to intend on initializer_list being a literal type. However, it doesn't look like it's an explicit requirement, and seems to be a bug in the standard.

标准委员会似乎打算将initializer_list作为文字类型。但是,它看起来不像是一个明确的需求,而且在标准中似乎是一个bug。

From § 3.9.10.5:

从§3.9.10.5:

A type is a literal type if it is:
- a class type (Clause 9) that has all of the following properties:
- - it has a trivial destructor,
- - it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
- - all of its non-static data members and base classes are of non-volatile literal types.

类型是一个文字类型,如果是:——一个类类型(条款9)有以下属性:——它有一个微不足道的析构函数,——它是一个集合的类型(8.5.1)或至少有一个constexpr构造函数或构造函数模板,不是构造函数复制或移动,和——所有的非静态数据成员和基类的非易失性文字类型。

From § 18.9.1:

从§18.9.1:

namespace std {
  template<class E> class initializer_list {
  public:
    /* code removed */
    constexpr initializer_list() noexcept;
    // No destructor given, so trivial
    /* code removed */
  };
}

This satisfies the first and second requirements.

这满足了第一个和第二个需求。

For the third requirement though:

至于第三项规定:

From § 18.9.2 (emphasis mine):

我从§18.9.2(重点):

An object of type initializer_list<E> provides access to an array of objects of type const E. [Note: A pair of pointers or a pointer plus a length would be obvious representations for initializer_list. initializer_list is used to implement initializer lists as specified in 8.5.4. Copying an initializer list does not copy the underlying elements.
—end note]

类型initializer_list 的对象提供对类型const . E的对象数组的访问。[注意:一对指针或指针加上长度将是initializer_list的明显表示。initializer_list用于实现8.5.4中指定的初始化列表。复制初始化器列表不复制底层元素。端注)

So there is no requirement for the private members of the implementation of initializer_list to be non-volatile literal types; however, because they mention that they believe a pair of pointers or a pointer and a length would be the "obvious representation," they probably didn't consider that someone might put something non-literal in the members of initializer_list.

因此,initializer_list实现的私有成员不需要非易失性文字类型;然而,由于他们提到他们相信一对指针或一个指针和一个长度将是“明显的表示”,他们可能没有想到有人可能会在initializer_list的成员中放入非文字的东西。

I'd say that it's both a bug in clang and the standard, probably.

我想说的是,它可能是clang和标准的缺陷。

#1


5  

The standard committee seems to intend on initializer_list being a literal type. However, it doesn't look like it's an explicit requirement, and seems to be a bug in the standard.

标准委员会似乎打算将initializer_list作为文字类型。但是,它看起来不像是一个明确的需求,而且在标准中似乎是一个bug。

From § 3.9.10.5:

从§3.9.10.5:

A type is a literal type if it is:
- a class type (Clause 9) that has all of the following properties:
- - it has a trivial destructor,
- - it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
- - all of its non-static data members and base classes are of non-volatile literal types.

类型是一个文字类型,如果是:——一个类类型(条款9)有以下属性:——它有一个微不足道的析构函数,——它是一个集合的类型(8.5.1)或至少有一个constexpr构造函数或构造函数模板,不是构造函数复制或移动,和——所有的非静态数据成员和基类的非易失性文字类型。

From § 18.9.1:

从§18.9.1:

namespace std {
  template<class E> class initializer_list {
  public:
    /* code removed */
    constexpr initializer_list() noexcept;
    // No destructor given, so trivial
    /* code removed */
  };
}

This satisfies the first and second requirements.

这满足了第一个和第二个需求。

For the third requirement though:

至于第三项规定:

From § 18.9.2 (emphasis mine):

我从§18.9.2(重点):

An object of type initializer_list<E> provides access to an array of objects of type const E. [Note: A pair of pointers or a pointer plus a length would be obvious representations for initializer_list. initializer_list is used to implement initializer lists as specified in 8.5.4. Copying an initializer list does not copy the underlying elements.
—end note]

类型initializer_list 的对象提供对类型const . E的对象数组的访问。[注意:一对指针或指针加上长度将是initializer_list的明显表示。initializer_list用于实现8.5.4中指定的初始化列表。复制初始化器列表不复制底层元素。端注)

So there is no requirement for the private members of the implementation of initializer_list to be non-volatile literal types; however, because they mention that they believe a pair of pointers or a pointer and a length would be the "obvious representation," they probably didn't consider that someone might put something non-literal in the members of initializer_list.

因此,initializer_list实现的私有成员不需要非易失性文字类型;然而,由于他们提到他们相信一对指针或一个指针和一个长度将是“明显的表示”,他们可能没有想到有人可能会在initializer_list的成员中放入非文字的东西。

I'd say that it's both a bug in clang and the standard, probably.

我想说的是,它可能是clang和标准的缺陷。