为什么将#std :: initializer_list`定义为文字类型?

时间:2014-12-16 01:16:42

标签: c++ language-lawyer c++14 initializer-list constexpr

这是对此问题的跟进:Is it legal to declare a constexpr initializer_list object?

从C ++ 14开始,std::initializer_list类的所有方法都标有constexpr。能够通过执行初始化实例似乎很自然 constexpr std::initializer_list<int> list = {1, 2, 3}; 但是Clang 3.5抱怨list没有被常量表达式初始化。 As dyp pointed out in a commentstd::initializer_list作为文字类型的任何要求似乎都已从规范中消失。

如果我们甚至不能将类完全定义为constexpr,那么将一个类完全定义为constexpr的重点是什么?这是标准中的疏忽,将来会得到修复吗?

2 个答案:

答案 0 :(得分:5)

标准委员会似乎打算将initializer_list作为文字类型。但是,它看起来并不是一个明确的要求,似乎是标准中的一个错误。

来自§3.9.10.5:

  

类型是文字类型,如果是:
   - 具有以下所有属性的类类型(第9条):
   - 它有一个简单的析构函数,
   - - 它是聚合类型(8.5.1)或至少有一个 constexpr 构造函数或构造函数模板,它不是复制或移动构造函数,并且
   - - 它的所有非静态数据成员和基类都是非易失性文字类型。

来自§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 */
  };
}

这符合第一和第二要求。

对于第三个要求:

从§18.9.2(强调我的):

  

类型为initializer_list<E>的对象提供对const E类型对象数组的访问。 [注意:一对指针或指针加上长度将是initializer_list的明显表示。 initializer_list用于实现8.5.4中指定的初始化列表。复制初始化列表不会复制基础元素    - 后注]

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

我说这可能是铿锵声和标准中的错误,可能。

答案 1 :(得分:0)

我记得在C ++ 11发布之后不久,我正在创建一个initializer_list,其单个成员分配了动态内存,因此它们具有非平凡的d'tor,因此,initializer_list具有非平凡的d'tor。在某些情况下,我认为我是在部分构造initializer_list时抛出的,其中所构造的部分没有被破坏,导致内存泄漏。我确定编译器已经修复。