无法从braced-init-list构造constexpr数组

SU3*_*SU3 14 c++ arrays constructor constexpr c++14

我已经实现了constexpr这样的数组:

template <typename T>
class const_array {
  const T* p;
  unsigned n;
public:
  template <unsigned N>
  constexpr const_array(const T(&a)[N]): p(a), n(N) { }

  constexpr unsigned size() const { return n; }
};

int main(int argc, char* argv[]) {
  // works
  static_assert(const_array<double>{{1.,2.,3.}}.size() == 3);

  // doesn't compile
  constexpr const_array<double> a{{1.,2.,3.}};
  static_assert(a.size() == 3);
}
Run Code Online (Sandbox Code Playgroud)

为什么第一次static_assert编译,但初始化a失败?我正在使用gcc 6.2.0.我越来越

: In function 'int main(int, char**)':
: error: 'const_array<double>{((const double*)(&<anonymous>)), 3u}' is not a constant expression
   constexpr const_array<double> a{{1.,2.,3.}};
                                        ^
test/const_array.cc:17:3: error: non-constant condition for static assertion
   static_assert(a.size() == 3);
   ^~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

Pot*_*ter 11

编译器抱怨初始化a.p器不是常量表达式.它失败§5.20/ 5.2:

如果值是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象结尾的地址(5.7),函数的地址或空指针值

换句话说,只有链接器已知的指针值才是有效常量.(另外,在你的例子中,指针是悬空的.)

第一个static_assert不会跳过它因为p被丢弃而且值n是一个常量表达式.常量表达式可能具有非常量子表达式.

这有效:

static constexpr double arr[] = { 1.,2.,3. };
constexpr const_array<double> a{ arr };
static_assert( a.size() == 3 );
Run Code Online (Sandbox Code Playgroud)

感谢@ Jarod42在评论中指出了问题.