嵌套结构体打破constexpr尽管与全局相同 [英] Nested struct breaks constexpr despite being identical to global ones

查看:235
本文介绍了嵌套结构体打破constexpr尽管与全局相同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用以下代码时遇到问题:

I'm having trouble with the following code:

template<typename T>
constexpr int get(T vec) {
  return vec.get();
}

struct coord {
  constexpr int get() const { return x; }
  int x;
};

struct foo {
    struct coord2 {
      constexpr int get() const { return x; }
      int x;
    };
    constexpr static coord f = { 5 };
    constexpr static int g = get(f); // works

    constexpr static coord2 h = { 5 };
    constexpr static int i = get(h); // doesn't work
};

constexpr coord foo::f;
constexpr foo::coord2 foo::h;

int main(){}

本质上, get(f)被认为是一个常量表达式,但 get(h)不是。唯一改变的是一个使用全局结构 coord ,而另一个使用嵌套结构 coord2 。结构体的
体是相同的。

Essentially, get(f) is considered a constant expression, but get(h) is not. The only thing changed is that one uses a global struct coord, while the other uses a nested struct coord2. The structs' bodies are identical.

为什么是这样?

GCC错误:

test.cpp:20:35: error: field initializer is not constant

Clang错误:

test.cpp:20:26: error: constexpr variable 'i' must be initialized by a constant expression
    constexpr static int i = get(h); // doesn't work
                         ^   ~~~~~~
test.cpp:8:10: note: undefined function 'get' cannot be used in a constant expression
  return vec.get();
         ^
test.cpp:20:30: note: in call to 'get({5})'
    constexpr static int i = get(h); // doesn't work
                             ^
test.cpp:13:21: note: declared here
      constexpr int get() const { return x; }


推荐答案

,因为这显示您可以通过将 i 移动到 main()

It is a constant expression.... eventually, as this shows you can see by moving i into main():

  • http://ideone.com/lucfUi

错误消息很清楚发生了什么,这是 foo :: coord2 :: get() code>尚未定义,因为成员函数定义被延迟到封闭类的结束,以便它们可以使用稍后声明的成员。

The error messages are pretty clear what's going on, which is that foo::coord2::get() isn't defined yet, because member function definitions are delayed until the end of the enclosing class so that they can use members declared later.

这是一个但是如果 foo :: coord2 :: get()无法定义的话,会更奇怪的是,访问 foo :: g

It's a little surprising that the definition is delayed until the end of the outermost enclosing class, but you'd be even more surprised if foo::coord2::get() couldn't access foo::g.

标准与编译器btw一致。 9.2p2部分介绍

The Standard agrees with the compiler, btw. Part of section 9.2p2 says


在类 member-specification 内,类被视为完整(包括此类对象)的,,

Within the class member-specification, the class is regarded as complete within function bodies, default arguments, exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes).

不幸的是,我们只推断类声明的闭括号成为点对点类,这些延迟区域的定义。我相信这是标准中的一个缺陷,它没有明确说明。

Unfortunately, it's only inferred that the closing brace of the class declaration becomes the point-of-definition for these deferred regions. I believe it's a defect in the Standard that it doesn't say this explicitly.

另请参见:

  • http://stackoverflow.com/a/11523155/103167

这篇关于嵌套结构体打破constexpr尽管与全局相同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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