在C++14中,一个constexpr成员函数是否能够改变数据成员?

7

在C++14中,由于constexpr不再隐式地是const,因此一个constexpr成员函数能否修改类的数据成员:

struct myclass
{
    int member;
    constexpr myclass(int input): member(input) {}
    constexpr void f() {member = 42;} // Is it allowed?
};

2
你可以很容易地自己尝试一下... - TemplateRex
1
又一个重复的问题 - TemplateRex
1
@TemplateRex,我不喜欢“自己试试”的评论,因为有很多情况下尝试可能看起来有效,但程序仍然是错误的。对于constexpr,我们有许多不符合规范的情况,例如这个这个 - Shafik Yaghmour
@ShafikYaghmour 我理解你的观点,但在这种情况下,问题几乎没有经过任何研究,有一些重复的问题。虽然 OP 有时会问一些非常有趣的问题,但也有一个倾向于不做功课就快速提问。还要注意的是,你给出的两个 Q&A 都有可编译的代码示例... - TemplateRex
2个回答

3
据我所知,是的。限制条件来自[dcl.constexpr]:
- constexpr函数的定义必须满足以下约束条件: - 它不能是虚函数(10.3); - 其返回类型必须是字面类型; - 每个参数类型都必须是字面类型; - 它的函数体必须是“= delete”、“= default”或不包含以下内容的复合语句: - asm-definition, - goto语句, - try-block或 - 非字面类型或静态或线程存储期或未执行初始化的变量的定义。
该函数符合所有这些要求。

3
是的,我相信这个变化始于提案N3598:constexpr成员函数和隐式const,最终成为N3652:放宽constexpr函数的限制的一部分,该提案改变了第7.1.5节第3段中函数体中允许的内容白名单:

其函数体应该是= delete、= default或者只包含以下内容的复合语句:

  • 空语句
  • static_assert声明
  • typedef声明和不定义类或枚举类型的别名声明
  • using声明
  • using指令
  • 以及恰好一个return语句;

变成了黑名单:

如果函数体为 = delete、= default 或不包含 asm 定义、goto 语句、try 块或非字面类型变量的定义,或者静态或线程存储持续时间变量的定义,或者未执行初始化,则其功能体应为复合语句。
并且还向第 C.3.3 条款 7:声明添加了以下注释:

Change: constexpr non-static member functions are not implicitly const member functions.

Rationale: Necessary to allow constexpr member functions to mutate the object.

Effect on original feature: Valid C++ 2011 code may fail to compile in this International Standard. For example, the following code is valid in C++ 2011 but invalid in this International Standard because it declares the same member function twice with different return types:

struct S {
 constexpr const int &f();
 int &f();
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接