【问题标题】:Mutating an int inside a constexpr function在 constexpr 函数中改变 int
【发布时间】:2015-11-01 09:24:57
【问题描述】:

为什么我可以这样做:

constexpr auto i_can() {
   int a = 8;
   a = 9;
   //...
}

但我不能这样做:

constexpr auto i_cannot() {
    std::array<int, 10> arr{};
    //I cannot
    arr[5] = 9;
}

我的问题是:

  1. 如果我可以改变 int,为什么我不能改变数组内部的 int
  2. 这是语言限制 (C++14) 还是标准库规范问题? reference std::array&lt;T, N&gt;::operator[](size_t) 当前不是 constexpr

【问题讨论】:

标签: c++ c++14 constexpr


【解决方案1】:

在 C++14 中引入了 constexpr 函数内对象的修改。但是,在修改例如赋值的标量很好,通过成员函数修改类对象仍然需要该成员函数为constexpr。不幸的是,正如您所提到的,当前的std::array 规范并未将非const operator[] 声明为constexpr
因此,§7.1.5/5 使您的定义格式错误:

对于非模板,非默认constexpr 函数 […],如果没有 参数值的存在使得函数的调用 […] 可以是核心常量表达式的求值子表达式 (5.20),[…],程序格式错误;无需诊断。

如果你想要完整的constexpr-ness,你可以暂时使用更现代的实现。例如。 Constainer::Array.

【讨论】:

  • 所以它与 bitset 发生相同:(
  • @GermánDiago 好吧,使用Constainer::Bitset :-P
  • 只是观察一下,“constainer”实际上是 Columbo 引用的库的名称,而不是拼写错误。
【解决方案2】:

这是标准库的一个限制,因为您可以修改 constexpr 中的纯 C 数组:

#include <iostream>

constexpr auto demo()
{
   int arr[10] = {};
   arr[5] = 9;
   return arr[5];
}

int main()
{
    static_assert(demo() == 9, "");
    std::cout << demo() << std::endl;
    return 0;
}   

DEMO

输出

9

如果您将constexpr 添加到operator[] 的实现array,您也可以在constexpr 中使用此运算符。

DEMO

【讨论】:

  • 这是猜测还是答案?
  • 您的代码不能证明demo 在被调用时产生了一个常量表达式。你必须写例如static_assert(demo() == 9, ""); 是肯定的。
  • @Columbo 感谢您的提示,我添加了static_assert
  • @ʎǝɹɟɟɟǝſ 我想这是一个答案:)
  • @m.s.你怎么知道的?
猜你喜欢
  • 2020-10-08
  • 2018-12-05
  • 1970-01-01
  • 2020-12-11
  • 2020-02-19
  • 1970-01-01
  • 2021-04-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多