我正在尝试编写一个具有多个静态constexpr值的类;这似乎是不允许的,因为constexpr声明需要类声明中不可用的类的定义。我的第一次尝试的MCV看起来像这样:
struct A {
constexpr A(float x) : _x(x) {}
float _x;
static constexpr A y = A(1.f);
// gcc-5.1:
// error: invalid use of incomplete type 'struct A'
// static constexpr A y = A(1.f);
// ^
// msvc-14:
// error C2027: use of undefined type 'A'
// note: see declaration of 'A'
// note: see declaration of 'A'
// error C2079: 'public: static A const A::y' uses undefined struct 'A'
};
我的下一次尝试是声明一个'常量'类(隐式转换为数据类,此处未显示)。这似乎工作正常:
struct B_constant {
constexpr B_constant(float x) : _x(x) {}
float _x;
};
struct B {
static constexpr B_constant y = B_constant(1.f);
};
但它有点难看,所以我想我会尝试将常量类作为数据类的嵌套类,但这样做不工作:
struct C {
struct C_constant {
constexpr C_constant(float x) : _x(x) {}
float _x;
};
static constexpr C_constant y = C_constant(1.f);
// gcc-5.1:
// error: 'constexpr C::C_constant::C_constant(float)' called in a constant expression
// static constexpr C_constant y = C_constant(1.f);
// ^
// msvc-14:
// error C2131: expression did not evaluate to a constant
// note: failure was caused by call of undefined function or one not declared 'constexpr'
// note: see usage of 'C::C_constant::C_constant'
};
我注意到失败类似于声明constexpr构造函数时的错误,但是在数据类中使用它之后定义它:
struct D_constant {
constexpr D_constant(float x);
float _x;
};
struct D {
static constexpr D_constant y = D_constant(1.f);
// gcc-5.1:
// error: 'constexpr D_constant::D_constant(float)' used before its definition
// static constexpr D_constant y = D_constant(1.f);
// ^
// msvc-14:
// error C2131: expression did not evaluate to a constant
// note: failure was caused by call of undefined function or one not declared 'constexpr'
// note: see usage of 'D::D_constant::D_constant'
};
constexpr D_constant::D_constant(float x) : _x(x) {}
任何人都可以了解第三个例子的情况吗?尽管嵌套类声明已完成,但似乎编译器无法在嵌套类中找到constexpr构造函数的定义。有谁知道一个更好的方法来完成我想要做的事情?
答案 0 :(得分:0)
如上所述here:
在类说明符的结束时,类被视为完全定义的对象类型(或完整类型)。 [...]否则在其自己的类成员规范中被认为是不完整的。
其中[...]
是未提及嵌套类的异常列表。
This定义成员规范:
类定义中的成员规范声明了该类的完整成员集;其他任何成员都无法添加。类的成员是数据成员,成员函数,嵌套类型,枚举器以及其成员模板和特化。 [...]
因此,嵌套类被认为是类规范的一部分,只有在您拥有完整类型(即结束}
时,才会引用它们,并将所提到的异常放在一边)。
数据成员也是成员规范的一部分,在声明此成员时,必须将该类视为不完整
请注意,使用名称C_constant
,您实际上使用的是限定名C::C_constant
,这是C
定义的一部分。 <{1}}中可以使用较短标识符引用它的事实不会改变其性质。
答案 1 :(得分:0)
有谁知道有更好的方法来完成我想要做的事情?
A::y
对象而不是函数或函子可能并不重要。
如果没有,你可以解决障碍,如:
struct A {
constexpr A(float x) : _x(x) {}
float _x;
static constexpr A y() {
return A(1.f);
}
};
constexpr A y = A::y();
static_assert(y._x == 1.f,"");