与正在定义的类具有相同类型的静态constexpr成员 [英] static constexpr member of same type as class being defined

查看:105
本文介绍了与正在定义的类具有相同类型的静态constexpr成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



尝试1:

我想要一个类C的静态constexpr成员类型C.这是可能在C ++ 11吗?

  struct Foo {
constexpr Foo(){}
static constexpr Foo f = Foo
};
constexpr Foo Foo :: f;

g ++ 4.7.0说:无效使用不完全类型指的是 Foo()



尝试2:



struct Foo {
constexpr Foo(){}
static constexpr Foo f;
};
constexpr Foo Foo :: f = Foo();

现在问题是缺少一个初始化器 constexpr

尝试3:

  struct Foo {
constexpr Foo(){}
static const Foo f;
};
constexpr Foo Foo :: f = Foo();

现在g ++抱怨重新声明 Foo :: f 不同于 constexpr

解决方案


(§9.4.2/ 3)[...]文字类型的静态数据成员可以在
类定义中使用constexpr说明符声明;如果是,其声明应指定一个括号或初始值化器,其中作为赋值语句的每个初始化子句都是一个常量表达式。 [...]


从上面的内容(以及在静态数据中没有关于非文字类型的单独语句成员声明),我相信, constexpr 的静态数据成员必须是文字类型(如§3.9/ 10定义) ,,它必须将定义包含在声明中。后面的条件可以通过使用下面的代码来满足:

  struct Foo {
constexpr Foo b $ b static constexpr Foo f {};
};

这与您的Attempt 1类似,但没有类外部定义。



但是,因为在声明/定义静态成员时 Foo 不完整,编译器不能检查它是否



请注意,有一个字面类型(如§3.9/ 10中定义),因此它拒绝代码。此后C ++ - 11文档(N3308),其中讨论了 constexpr ,并提出修正建议。具体来说,建议的措辞部分建议修改§3.9/ 10,这意味着包含不完全类型作为一种文字类型。如果该修正案在未来版本的标准中被接受,您的问题将得到解决。


I would like a class C to have a static constexpr member of type C. Is this possible in C++11?

Attempt 1:

struct Foo {
    constexpr Foo() {}
    static constexpr Foo f = Foo();
};
constexpr Foo Foo::f;

g++ 4.7.0 says: 'invalid use of incomplete type' referring to the Foo() call.

Attempt 2:

struct Foo {
    constexpr Foo() {}
    static constexpr Foo f;
};
constexpr Foo Foo::f = Foo();

Now the problem is the lack of an initializer for the constexpr member f inside the class definition.

Attempt 3:

struct Foo {
    constexpr Foo() {}
    static const Foo f;
};
constexpr Foo Foo::f = Foo();

Now g++ complains about a redeclaration of Foo::f differing in constexpr.

解决方案

If I interpret the Standard correctly, it isn't possible.

(§9.4.2/3) [...] 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. [...]

From the above (along with the fact that there is no separate statement about non-literal types in static data member declarations), I believe it follows that a static data member that is constexpr must be a literal type (as defined in §3.9/10), and it must have its definition included in the declaration. The latter condition could be satisfied by using the following code:

struct Foo {
  constexpr Foo() {}
  static constexpr Foo f {};
};

which is similar to your Attempt 1, but without the class-external definition.

However, since Foo is incomplete at the time of declaration/definition of the static member, the compiler can't check whether it is a literal type (as defined in §3.9/10), so it rejects the code.

Note that there is this post-C++-11 document (N3308) which discusses various problems of the current definition of constexpr in the Standard, and makes suggestions for amendments. Specifically, the "Proposed Wording" section suggests an amendment of §3.9/10 that implies the inclusion of incomplete types as one kind of literal type. If that amendment was to be accepted into a future version of the Standard, your problem would be solved.

这篇关于与正在定义的类具有相同类型的静态constexpr成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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