Constexpr放置新品?

时间:2017-01-10 23:05:33

标签: c++ language-lawyer constexpr placement-new

C ++标准专门禁止在常量表达式中调用new(N4296第5.20节[expr.const]):

  

条件表达式e是核心常量表达式,除非根据抽象机器(1.9)的规则评估e将评估以下表达式之一:

     

...

     

- 一个新表达式(5.3.4);

此禁令(据我所见)扩展到{em>所有形式的new,包括新的展示位置。但是,由于placement new实际上并没有分配任何内存,只是在给定位置运行构造函数,并且因为在constexpr上下文中获取变量的地址是合法的(事实上,std::addressof将是在C ++中的constexpr 17),在我看来,这个禁令(原则上至少)可以放宽,以允许在constexpr函数中放置新的。

所以我的问题是,我错过了什么吗?在constexpr函数中禁止放置new是否有充分的理由?

(对于上下文:当前规则几乎要求启用constexpr的和类型如std::variant实现为递归联合。能够使用std::aligned_storage和放置等内容会更好新的,但目前这是不可能的。)

3 个答案:

答案 0 :(得分:1)

#include <cstdint>
#include <iostream>

class A {
public:
    constexpr A() = default;
    int a = 5;
};

constexpr int foo() {
    uint8_t space[sizeof(A)];
    new(space) A();
    A& a = *reinterpret_cast<A*>(space);
    return a.a;
}

int main() {
  std::cout << foo() << std::endl;
}

编译器可以理解上述程序当然是可以想象的。通常我认为这是不可行的,因为确保放置参数始终指向本地内存所需的复杂性。

我不认为&#34;记忆&#34;的概念甚至适用于constexpr函数,因为它们通常在编译时进行评估。

答案 1 :(得分:1)

placement new与当前的constexpr世界不能很好地融合在一起,因为它允许使用其底层字节表示(带有值初始化)来构建对象。而且这在标准中没有定义(提醒一下,甚至在constexpr中都没有二补码)

通过查看C ++标准讨论,它可以允许以后查看对象类型表示形式(因为您仍然持有字节数组)

答案 2 :(得分:-1)

没有任何概念上的原因,新的放置无法奏效。我认为这是一个疏忽,放置new基本上只是在预定义的内存位置调用构造函数。

确保placement new参数具有有效的参数位置并不比确保对随机指针的写入有效更难。