静态模板化constexpr嵌套类成员 [英] Static templated constexpr nested class member

查看:84
本文介绍了静态模板化constexpr嵌套类成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下带有嵌套类Bar的示例类Foo,所有内容都是constexpr:

I have the following sample class Foo with nested class Bar and everything is constexpr:

class Foo
{
private:
    template <typename T>
    struct Bar
    {
        constexpr Bar(){}
        constexpr int DoTheThing() const
        {
            return 1;
        }
    };

public:
    constexpr static auto b = Bar<int>{};
    constexpr Foo() {}
    constexpr int DoTheThing() const
    {
        return b.DoTheThing();
    }
};

我想测试调用Foo::DoTheThing返回1:

int main()
{
   constexpr Foo f;
   static_assert(f.DoTheThing() == 1, "DoTheThing() should return 1");
}

GCC和Clang都在这里抱怨,但MSVC没有

GCC and Clang both complain here, but MSVC does not

GCC 说:

错误:constexpr Foo::Bar<T>::Bar() [with T = int]在定义之前使用

constexpr static auto b = Bar<int>{};

C语:

错误:constexpr变量b必须通过常量表达式初始化

error: constexpr variable b must be initialized by a constant expression

constexpr static auto b = Bar<int>{};

我无法确定标准是否不允许这样做,但是我猜测b是不完整的类型.

I cannot tell if the standard disallows this, but my guess is that somehow b is an incomplete type.

让事情变得更有趣的是,如果删除constexpr,或者将Bar的定义移到了Foo之外,我都可以使用GCC和Clang.

What makes things more interesting is that I can get GCC and Clang to behave if I remove the constexpr, or if I move the definition of Bar outside of Foo.

请注意,此问题是受以下因素启发的:

Note that this question was inspired by the following:

  • Simple constexpr LookUpTable in C++14 (my problem is one part of this unanswered question's problem)
  • Nested struct breaks constexpr despite being identical to global ones (this seems to provide some insight into what's going on)

推荐答案

来自n4140

第9.2.2节[class.mem](强调我的)

§ 9.2.2 [class.mem] (Emphasis mine)

一个类被认为是完全定义的对象类型(3.9)(或 完整类型)在 class-specifier 的结尾}处.内 类 member-specification ,该类被认为是完整的 函数体,默认参数,使用声明介绍 继承构造函数(12.9),异常规范和 非静态数据成员(包括 嵌套类中的此类内容). 否则,它被认为是不完整的 在其自己的类 member-specification 中.

A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, using-declarations introducing inheriting constructors (12.9), exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

Clang和GCC是正确的.当您声明您的static constexpr成员时,该类不被认为是完整的,因此您无法构造它.这就是为什么将Bar的定义移出或删除static constexpr的原因的原因(因为定义非静态成员时 被认为是完整的)

Clang and GCC are correct. The class is not considered complete when you are declaring your static constexpr member, so you cannot construct it. This is why moving the definition of Bar out or removing the static constexpr works (because it is considered complete when defining non-static members)

要澄清一下,尤其要考虑以下问题:内部类的静态constexpr成员

To clarify, especially considering this question: Static constexpr member of an inner class

我上面引用的标准语基本上是指<​​em>除非另有说明,否则一个类在其 * 内被认为是不完整的. staticconstexprstatic constexpr初始值设定项不属于否则指定的部分,因此,我们不能在类内声明的任何内容使用包括嵌套的类类型.

The standardese I quoted above basically means that unless otherwise specified a class is regarded incomplete within itself *. A static, constexpr, or static constexpr initializer does not fall under the otherwise specified portion, and therefore we can not use anything declared within the class, which includes a nested class type.

*表示您不能在类声明中使用它或它的成员.最众所周知的例外是在成员函数中.

这篇关于静态模板化constexpr嵌套类成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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