繁体   English   中英

静态模板化constexpr嵌套类成员

[英]Static templated constexpr nested class member

我有以下示例类Foo与嵌套类Bar ,一切都是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说:

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

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

Clang

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

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

我不知道标准是否允许这样做,但我的猜测是某种方式b是不完整的类型。

让事情变得更有趣的是,如果我删除constexpr ,或者如果我在Foo之外移动Bar的定义,我可以让GCC和Clang行事。

哪些编译器是正确的?

请注意,此问题的灵感来自以下方面:

从n4140开始

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

一类被认为是在闭合完全定义的对象类型(3.9)(或完全型) }类指定符 在类成员规范中 ,该类在函数体,缺省参数,引入继承构造函数(12.9)的使用声明, 异常规范和非静态数据成员的括号或等于初始化器中被视为完整(包括嵌套类中的这类东西)。 否则,它在其自己的类成员规范中被视为不完整

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


澄清一下,特别是考虑这个问题: 内部类的静态constexpr成员

我在上面引用的标准基本上意味着除非另有规定否则一个类本身被视为不完整* staticconstexprstatic constexpr初始值设定项不属于其他指定部分,因此我们不能使用类中声明的任何内容 ,包括嵌套类类型。

*意味着您不能在类声明中使用它或它的成员。 最着名的例外是成员函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM