gpt4 book ai didi

c++ - constexpr 使用静态函数初始化静态成员

转载 作者:IT老高 更新时间:2023-10-28 12:43:41 24 4
gpt4 key购买 nike

要求

我想要一个从 constexpr 函数计算的 constexpr 值(即编译时常量)。我希望这两个范围都在一个类的命名空间内,即一个静态方法和一个类的静态成员。

第一次尝试

我首先以(对我而言)显而易见的方式写了这个:

class C1 {
constexpr static int foo(int x) { return x + 1; }
constexpr static int bar = foo(sizeof(int));
};

g++-4.5.3 -std=gnu++0x 说:

error: ‘static int C1::foo(int)’ cannot appear in a constant-expression
error: a function call cannot appear in a constant-expression

g++-4.6.3 -std=gnu++0x 提示:

error: field initializer is not constant

第二次尝试

好吧,我想,也许我必须把东西移出类。所以我尝试了以下方法:

class C2 {
constexpr static int foo(int x) { return x + 1; }
constexpr static int bar;
};
constexpr int C2::bar = C2::foo(sizeof(int));

g++-4.5.3 将毫无怨言地编译它。不幸的是,我的其他代码使用了一些基于范围的 for 循环,所以我必须至少有 4.6。现在我仔细观察 support list ,看来 constexpr 也需要 4.6。而使用 g++-4.6.3 我得到了

3:24: error: constexpr static data member ‘bar’ must have an initializer
5:19: error: redeclaration ‘C2::bar’ differs in ‘constexpr’
3:24: error: from previous declaration ‘C2::bar’
5:19: error: ‘C2::bar’ declared ‘constexpr’ outside its class
5:19: error: declaration of ‘const int C2::bar’ outside of class is not definition [-fpermissive]

这对我来说听起来很奇怪。这里的“constexpr 有什么不同”?我不想添加 -fpermissive 因为我更喜欢严格检查我的其他代码。将 foo 实现移到类主体之外没有可见的效果。

预期答案

有人可以解释这里发生了什么吗?我怎样才能实现我正在尝试做的事情?我主要对以下类型的答案感兴趣:

  • 在 gcc-4.6 中实现此功能的一种方法
  • 观察到后来的 gcc 版本可以正确处理其中一个版本
  • 一个指向规范的指针,根据该规范,我的至少一个构造应该工作,这样我就可以让 gcc 开发人员真正让它工作起来
  • 根据规范,我想要的信息是不可能的,最好有一些关于此限制背后的基本原理的信息

也欢迎其他有用的答案,但可能不会那么容易被接受。

最佳答案

标准要求(第 9.4.2 节):

A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression.

在您的“第二次尝试”和 Ilya 回答中的代码中,声明没有 brace-or-equal-initializer

你的第一个代码是正确的。不幸的是 gcc 4.6 不接受它,而且我不知道有什么地方可以方便地尝试 4.7.x(例如 ideone.com 仍然停留在 gcc 4.5 上)。

这是不可能的,因为不幸的是,标准禁止在类已完成的任何上下文中初始化静态 constexpr 数据成员。 9.2p2 中 brace-or-equal-initializers 的特殊规则仅适用于 非静态 数据成员,但这是静态的。

最可能的原因是 constexpr 变量必须在成员函数体内作为编译时常量表达式可用,因此变量初始化器在函数体之前完全定义 - - 这意味着函数在初始化器的上下文中仍然是不完整的(未定义),然后这个规则开始生效,使得表达式不是一个常量表达式:

an invocation of an undefined constexpr function or an undefined constexpr constructor outside the definition of a constexpr function or a constexpr constructor;

考虑:

class C1
{
constexpr static int foo(int x) { return x + bar; }
constexpr static int bar = foo(sizeof(int));
};

关于c++ - constexpr 使用静态函数初始化静态成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11522399/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com