为什么在constexpr非成员函数中访问全局非常量变量是不合法的

时间:2017-07-27 14:59:41

标签: c++ c++14 constexpr

int d = 1;
constexpr void add()
{
    d++;
}

int main()
{

}

GCC 7.1将报告以下错误。错误消息非常清楚。问题是我在constexpr中没有看到任何明确的解释来描述它是非法的。

有人可以解释这个案例中规定的规则违反了哪些规则吗?


main.cpp: In function 'constexpr void add()':

main.cpp:8:1: error: the value of 'd' is not usable in a constant expression

 }

 ^

main.cpp:4:5: note: 'int d' is not const

 int d = 1;

     ^

2 个答案:

答案 0 :(得分:2)

来自cppreference

  

核心常量表达式是在任何子表达式中没有以下任何一个的任何表达式(忽略未评估的表达式,例如sizeof的操作数或内置的右操作数&&当左操作数计算为false时)

     

...

     

16)修改对象,除非该对象具有非易失性文字类型,并且其生命周期始于表达式的评估。

在您的示例中,add的生命周期是在评估<source-file src="src/android/src/net/mydomain/myplugin/MyClass.java" target-dir="src/mydomain/myplugin" /> 之前开始的 - 因此{{1}}内{{1}}的任何修改都是非法的。引用上的示例专门用于递增,但这适用于所有修改。

编辑:没有引用标准,因为据我所知,你必须购买它......

答案 1 :(得分:0)

从您参考标准的角度来看,评论很好,但希望这是一个更直观的解释。

在编译时,constexpr函数必须可简化为常量表达式。由于您正在与函数中的常规非const int进行交互,因此编译器无法确定在任何情况下d++是什么。考虑以下情况:

int d;
constexpr void add() {
    d++;
}

void foo() {
    int n;
    std::cin >> n;
    d = n;
    add();
}

在这种情况下,dfoo()的值在编译时是不确定的,因此,无法确定您希望add()离开的常量表达式。我希望有所帮助。