静态模板化constexpr嵌套类成员 [英] Static templated constexpr nested class member
问题描述
我有以下带有嵌套类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:
- C ++ 14中的简单constexpr LookUpTable (我的问题是此未解答问题的一部分)
- 尽管嵌套结构与全局结构相同,但嵌套结构却破坏了constexpr (这似乎为正在发生的事情提供了一些见识)
- 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>除非另有说明,否则一个类在其 * 内被认为是不完整的. static
,constexpr
或static 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屋!