通过引用传入的值的 constexpr
constexpr for values passed in by reference
我有这段代码可以编译
#include <bitset>
struct A{
std::bitset<50> b; };
void test(A a){
static_assert(sizeof(int)*8 < a.b.size(), "can't accomodate int in bitset");
int x = 5;
a.b = x; }
int main(){
A a;
test(a); }
但这不是
#include <bitset>
struct A{
std::bitset<50> b;
};
void test(A& a){
static_assert(sizeof(int)*8 < a.b.size(), "can't accomodate int in bitset");
int x = 5;
a.b = x;
}
int main(){
A a;
test(a);
}
失败并出现此错误
const.cpp: In function ‘void test(A&)’: const.cpp:8:5: error: non-constant condition for static assertion
static_assert(sizeof(int)*8 < a.b.size(), "can't accomodate int in bitset");
const.cpp:8:5: error: ‘a’ is not a constant expression
为什么 a.b.size()
在第二种情况下不被视为 constexpr?根据 reference,std::bitset::size()
的 constexpr
不是应该被视为 const 的那个吗?还是第二种情况下传递的非常量引用会触发编译器产生错误?
编译器版本:
Ubuntu 14.0.4 上的 g++ 4.8.4,使用 g++ const.cpp -std=c++1y
编译
根据其他人的指点1,它似乎是 gcc 和 clang 中的编译器错误。它在 gcc 5.1 中已修复,但截至 2019 年 7 月 25 日,它仍然是 clang 8.0
中的错误
这是gcc的一个bug,在5.1版本中引入。查看其他答案。
1)
Seems to be a (now fixed) compiler bug as it complies with the latest gcc version: https://godbolt.org/z/ZaDXED
A& a
不能 用于常量表达式 ,使你的程序格式错误。
禁止 a.b.size()
成为常量表达式且 a
为 A&
的规则如下:
[expr.const]/3
A variable is usable in constant expressions after its initializing declaration is encountered if it is a constexpr variable, or it is of reference type or of const-qualified integral or enumeration type, and its initializer is a constant initializer.
在你的例子中,变量 a
是:
- 未声明 [=18=](作为函数参数,没有意义),
- 并且不是整型或枚举类型,
- and 不是一个引用,它的初始化是一个常量初始值设定项:
[expr.const]/2
A constant initializer for a variable or temporary object o
is an initializer for which interpreting its full-expression as a constant-expression results in a constant expression, except that if o
is an object, such an initializer may also invoke constexpr constructors for o
and its subobjects even if those objects are of non-literal class types.
采用以下简化示例:
struct s { constexpr static bool true_value() { return true; } };
void assert_on(s const& ref)
{
static_assert(ref.true_value());
}
int main()
{
assert_on(s{});
}
gcc-9 错误地接受它1,但 clang-8 产生正确的诊断:
error: static_assert expression is not an integral constant expression
完整演示:https://godbolt.org/z/t_-Ubj
1) 这是 GCC bug #66477,从 5.1 版开始有效,尚未解决。
我有这段代码可以编译
#include <bitset>
struct A{
std::bitset<50> b; };
void test(A a){
static_assert(sizeof(int)*8 < a.b.size(), "can't accomodate int in bitset");
int x = 5;
a.b = x; }
int main(){
A a;
test(a); }
但这不是
#include <bitset>
struct A{
std::bitset<50> b;
};
void test(A& a){
static_assert(sizeof(int)*8 < a.b.size(), "can't accomodate int in bitset");
int x = 5;
a.b = x;
}
int main(){
A a;
test(a);
}
失败并出现此错误
const.cpp: In function ‘void test(A&)’: const.cpp:8:5: error: non-constant condition for static assertion
static_assert(sizeof(int)*8 < a.b.size(), "can't accomodate int in bitset");
const.cpp:8:5: error: ‘a’ is not a constant expression
为什么 a.b.size()
在第二种情况下不被视为 constexpr?根据 reference,std::bitset::size()
的 constexpr
不是应该被视为 const 的那个吗?还是第二种情况下传递的非常量引用会触发编译器产生错误?
编译器版本:
Ubuntu 14.0.4 上的 g++ 4.8.4,使用 g++ const.cpp -std=c++1y
根据其他人的指点1,它似乎是 gcc 和 clang 中的编译器错误。它在 gcc 5.1 中已修复,但截至 2019 年 7 月 25 日,它仍然是 clang 8.0
这是gcc的一个bug,在5.1版本中引入。查看其他答案。
1)
Seems to be a (now fixed) compiler bug as it complies with the latest gcc version: https://godbolt.org/z/ZaDXED
A& a
不能 用于常量表达式 ,使你的程序格式错误。
禁止 a.b.size()
成为常量表达式且 a
为 A&
的规则如下:
[expr.const]/3
A variable is usable in constant expressions after its initializing declaration is encountered if it is a constexpr variable, or it is of reference type or of const-qualified integral or enumeration type, and its initializer is a constant initializer.
在你的例子中,变量 a
是:
- 未声明 [=18=](作为函数参数,没有意义),
- 并且不是整型或枚举类型,
- and 不是一个引用,它的初始化是一个常量初始值设定项:
[expr.const]/2
A constant initializer for a variable or temporary object
o
is an initializer for which interpreting its full-expression as a constant-expression results in a constant expression, except that ifo
is an object, such an initializer may also invoke constexpr constructors foro
and its subobjects even if those objects are of non-literal class types.
采用以下简化示例:
struct s { constexpr static bool true_value() { return true; } };
void assert_on(s const& ref)
{
static_assert(ref.true_value());
}
int main()
{
assert_on(s{});
}
gcc-9 错误地接受它1,但 clang-8 产生正确的诊断:
error: static_assert expression is not an integral constant expression
完整演示:https://godbolt.org/z/t_-Ubj
1) 这是 GCC bug #66477,从 5.1 版开始有效,尚未解决。