编译和工作的错误静态常量初始化 [英] Wrong static const initialization that compiles and works

查看:28
本文介绍了编译和工作的错误静态常量初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,您只能在声明的同一行中初始化静态常量成员如果它们是整数类型.但是,我仍然能够初始化并使用一些静态常量双打:

As far as I know, you can only initialize static const members in the same line of their declaration if they are integral types . However, I was still able to initialize and use some static const doubles:

// compiles and works, values are indeed doubles
struct Foo1{ 
    static const double A=2.5;
    static const double B=3.2;
    static const double C=1.7;
};

// compiles, but values are cast to int
struct Foo2{
    static const int A=2;
    static const int B=3;
    static const double C=B/A; //becomes 1
};

// does not compile, Foo3::B cannot appear in a constant-expression
struct Foo3{ 
    static const int A=2;
    static const double B=3;
    static const double C=A/B; 
};

// does not compile, a cast to a type other than an integral or enumeration
// cannot appear in a constant-expression
struct Foo4{ 
    static const int A=2;
    static const int B=3;
    static const double C=(double)A/B; 
};

Foo2 编译但 Foo2::C 变为 1,所以也许它被视为一个 int,因为它在数字上是 1.Foo3 和 Foo4 甚至没有按预期编译.但是,我不明白为什么 Foo1 既能编译又能正常工作.这种特定用法是否被接受?是不是因为一些优化?(我试过使用 -O1 和 -O0)

Foo2 compiles but Foo2::C becomes 1, so maybe it is treated as an int as it is numerically one. Foo3 and Foo4 don't even compile, as expected. However, I don't understand why Foo1 both compiles and works correctly. Is this specific usage accepted? Is it because of some optimization? ( I've tried using -O1 and -O0)

注意:使用带有 cmake 的 GNU 5.2.0 并将标准设置为 C++98.切换到 C++11 工作正常(也就是说,不编译并要求将这些成员切换到 constexpr).

Note: using GNU 5.2.0 with cmake and setting the standard to C++98. Switching to C++11 works fine ( that is, does not compile and asks to switch those members to constexpr).

推荐答案

Foo1 情况确实不符合标准,如果我们使用 -std=c++98 -pedantic gcc 会发出如下警告(实时观看):

The Foo1 case is indeed non-conforming and if we build using -std=c++98 -pedantic gcc will warn as follows (see it live):

error: floating-point literal cannot appear in a constant-expression
 static const double A=2.5;
                       ^
warning: ISO C++ forbids initialization of member constant 'Foo1::A' of non-integral type 'const double' [-Wpedantic]

虽然在没有 -pedantic 的情况下编译不会产生任何错误或警告 (现场观看)

While compiling without -pedantic does not yield any error or warning (see it live)

所以这必须是一个扩展,如果我们使用 -std=C++98 -pedantic 使用 clang,我们会看到这条消息:

So this must be an extension and if we use clang using -std=C++98 -pedantic we see this message:

warning: in-class initializer for static data member of type 'const double' is a GNU extension [-Wgnu-static-float-init]
static const double A=2.5;
                    ^ ~~~

这似乎证实这是一个扩展.

which seems to confirm this is an extension.

这个浮点限制保留在 C++11 中以保持与 C++03 兼容并鼓励一致使用 constexpr 参见:double 类型的静态类成员的常量表达式初始值设定项.

This restriction on floating point was kept in C++11 to remain compatible with C++03 and to encourage consistent use of constexpr see: Constant expression initializer for static class member of type double.

这也是 Foo2 初始化 C 允许作为扩展的情况,除法的结果将是 int 因为类型结果的大小取决于操作数的类型,而不取决于您将其分配给什么.

This is also the case for Foo2 initializing C is allowed as an extension, the result of the division will be int since the type of the result depends on the type of the operands and does not depend on what you assign it to.

更新

这是一个折旧的扩展:

G++ 允许在类定义中使用初始值设定项声明 const 浮点类型的静态数据成员.该标准只允许 const 整数类型和 const 枚举类型的静态成员的初始值设定项,因此此扩展已被弃用,并将从未来版本中删除.

G++ allows static data members of const floating-point type to be declared with an initializer in a class definition. The standard only allows initializers for static members of const integral types and const enumeration types so this extension has been deprecated and will be removed from a future version.

有一个更详细的 gcc 错误报告,讨论了扩展的有效性和其他相关问题.

There is a more detailed gcc bug report that discusses the validity of the extension and other related issues around it.

使用 -pedantic 本身就足以将其转变为错误似乎很奇怪,有一个 涵盖该内容的 gcc 错误报告.

It seemed odd that using -pedantic was sufficient by itself to turn this into an error, there is a gcc bug report that covers that.

这篇关于编译和工作的错误静态常量初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆