c++ - 无法从花括号初始化列表构造 constexpr 数组

标签 c++ arrays constructor c++14 constexpr

我已经实现了一个像这样的 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);
}

为什么第一个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);
   ^~~~~~~~~~~~~

最佳答案

编译器提示 a.p 的初始化器不是常量表达式。 §5.20/5.2 失败:

if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object (5.7), the address of a function, or a null pointer value

换句话说,只有链接器知道的指针值才是有效的常量。 (此外,在您的示例中,指针是悬空的。)

第一个 static_assert 不会触发这个,因为 p 被丢弃并且 n 的值是一个常量表达式。常量表达式可能有非常量子表达式。

这行得通:

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

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

关于c++ - 无法从花括号初始化列表构造 constexpr 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41420301/

相关文章:

java - 如何让一个循环重复另一个循环?

java - 将数组的字符串输出到 java 中的 JTextArea

c++ - 上传到粘贴站

c++ - 移动构造函数是自动生成的吗?

c++ - Eclipse CDT 编译错误

javascript - Obj 构造函数中的 AJAX 回调

C++ 模板构造函数

C++:在 .lib 成功构建后在 VS2010 中创建 .dll 时出现 "unresolved external symbol"

javascript - JavaScript 中二维数组的切片/部分

c++ - 带默认参数的构造函数