[英]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成员
我在上面引用的标准基本上意味着除非另有规定 , 否则一个类本身被视为不完整* 。 static
, constexpr
或static constexpr
初始值设定项不属于其他指定部分,因此我们不能使用类中声明的任何内容 ,包括嵌套类类型。
*意味着您不能在类声明中使用它或它的成员。 最着名的例外是成员函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.