我想要一个从 constexpr
函数计算的 constexpr
值(即编译时常量).而且我希望这两个范围都在类的命名空间内,即静态方法和类的静态成员.
I want a constexpr
value (i.e. a compile-time constant) computed from a constexpr
function. And I want both of these scoped to the namespace of a class, i.e. a static method and a static member of the class.
我首先用(对我来说)显而易见的方式写了这个:
I first wrote this the (to me) obvious way:
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
好吧,我想,也许我必须把东西移出类体.所以我尝试了以下方法:
OK, I thought, perhaps I have to move things out of the class body. So I tried the following:
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.现在,我仔细查看了 支持列表,看来 constexpr
也需要 4.6.使用 g++-4.6.3
我得到
g++-4.5.3
will compile that without complaints. Unfortunately, my other code uses some range-based for
loops, so I have to have at least 4.6. Now that I look closer at the support list, it appears that constexpr
would require 4.6 as well. And with g++-4.6.3
I get
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
实现移到类体之外没有明显的效果.
This sounds really strange to me. How do things "differ in constexpr
" here? I don't feel like adding -fpermissive
as I prefer my other code to be rigurously checked. Moving the foo
implementation outside the class body had no visible effect.
有人可以解释一下这里发生了什么吗?我怎样才能实现我正在尝试做的事情?我主要对以下类型的答案感兴趣:
Can someone explain what is going on here? How can I achieve what I'm attempting to do? I'm mainly interested in answers of the following kinds:
也欢迎其他有用的答案,但可能不会那么容易被接受.
Other useful answers are welcome as well, but perhaps won't be accepted as easily.
标准要求(第 9.4.2 节):
The Standard requires (section 9.4.2):
可以在类定义中使用 constexpr
说明符声明文字类型的 static
数据成员;如果是这样,它的声明应指定一个 brace-or-equal-initializer 其中每个作为 assignment-expression 的 initializer-clause 都是一个常量表达式.
A
static
data member of literal type can be declared in the class definition with theconstexpr
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.
In your "second attempt" and the code in Ilya's answer, the declaration doesn't have a brace-or-equal-initializer.
你的第一个代码是正确的.不幸的是 gcc 4.6 不接受它,而且我不知道在哪里可以方便地尝试 4.7.x(例如 ideone.com 仍然停留在 gcc 4.5 上).
这是不可能的,因为不幸的是,标准禁止在类完成的任何上下文中初始化静态 constexpr
数据成员.9.2p2 中brace-or-equal-initializers 的特殊规则仅适用于非静态 数据成员,但这是静态的.
This isn't possible, because unfortunately the Standard precludes initializing a static constexpr
data member in any context where the class is complete. The special rule for brace-or-equal-initializers in 9.2p2 only applies to non-static data members, but this one is static.
最可能的原因是 constexpr
变量必须在成员函数体内部作为编译时常量表达式可用,所以变量初始化器完全在函数体之前定义 -- 这意味着函数在初始化器的上下文中仍然是不完整的(未定义的),然后这个规则开始生效,使得表达式不是一个常量表达式:
The most likely reason for this is that constexpr
variables have to be available as compile-time constant expressions from inside the bodies of member functions, so the variable initializers are completely defined before the function bodies -- which means the function is still incomplete (undefined) in the context of the initializer, and then this rule kicks in, making the expression not be a constant expression:
在constexpr
函数或constexpr<的定义之外调用未定义的
constexpr
函数或未定义的constexpr
构造函数/code> 构造函数;
an invocation of an undefined
constexpr
function or an undefinedconstexpr
constructor outside the definition of aconstexpr
function or aconstexpr
constructor;
考虑:
class C1
{
constexpr static int foo(int x) { return x + bar; }
constexpr static int bar = foo(sizeof(int));
};
这篇关于constexpr 使用静态函数初始化静态成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!