[英]Why does constexpr static member (of type class) require a definition?
==> See the full snippet code and compilation on coliru . ==> 在coliru上查看完整的代码片段和编译。
I have a LiteralType class filling constexpr
requirements :我有一个LiteralType类填充
constexpr
要求:
struct MyString
{
constexpr MyString(char const* p, int s) : ptr(p), sz(s) {}
constexpr char const* data() const { return ptr; }
constexpr int size() const { return sz; }
char const *ptr = 0;
int const sz = 0;
};
I use it as a constexpr static
member variable:我将它用作
constexpr static
成员变量:
struct Foo
{
int size() { return str_.size(); }
constexpr static MyString str_{"ABC",3};
};
int main()
{
Foo foo;
return ! foo.size();
}
But the linker says:但是链接器说:
(Clang-3.5 and GCC-4.9) (Clang-3.5 和 GCC-4.9)
undefined reference to `Foo::str_'
I have to define the constexpr static
member!我必须定义
constexpr static
成员!
(I do not specify the constructor parameters) (我没有指定构造函数参数)
constexpr MyString Foo::str_;
However if the constexpr static
member had been an int
the member would not have to be defined outside the class definition.但是,如果
constexpr static
成员是int
则不必在类定义之外定义该成员。 This is my understanding, but I am not sure...这是我的理解,但我不确定...
int
does not need to be defined outside the class declaration but MyString
requires this?int
不需要在类声明之外定义,但MyString
需要这个?constexpr static
member in a header file?constexpr static
成员是否有缺点?The One Definition rule tells us that we can not have more than one definition of an odr-used variable in a program.单一定义规则告诉我们,在一个程序中,一个odr-used变量的定义不能超过一个。 So if a variable is odr-used then you need to define it but you can not define it the header file since it may be included more than once with the whole program.
所以如果一个变量是 odr-used 那么你需要定义它,但你不能定义它的头文件,因为它可能被包含在整个程序中不止一次。 Odr-use violations do not require a diagnostic message and so you can violate this rule and the compiler is not obliged to notify you.
Odr 使用违规不需要诊断消息,因此您可以违反此规则,编译器没有义务通知您。
In your case you are indeed odr-using str_
, and you can not include the definition in the header file because that would violate the one definiton rule since it can be included more than once within the program.在您的情况下,您确实是使用 odr 的
str_
,并且您不能在头文件中包含该定义,因为这将违反一个定义规则,因为它可以在程序中多次包含。
It is interesting to note that if you had done the following it would not have been odr-used:有趣的是,如果您执行了以下操作,则不会使用 odr:
return str_.size_;
You would therefore not need to define the variable, which can have some odd consequences in some examples .因此,您不需要定义变量,这在某些示例中可能会产生一些奇怪的后果。 I doubt that really solves your problem long-term.
我怀疑这是否真的能长期解决你的问题。
The odr rules are covered in the draft C++ standard section 3.2
and they say: odr 规则包含在 C++ 标准草案第
3.2
节中,他们说:
A variable x whose name appears as a potentially-evaluated expression ex is odr-used unless applying the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.19) that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (4.1) is applied to e, or e is a discarded-value expression (Clause 5).
变量 x 其名称显示为潜在求值表达式 ex 是 odr-used 除非将左值到右值转换 (4.1) 应用到 x 产生一个不调用任何非平凡函数的常量表达式 (5.19) 并且,如果x 是一个对象,ex 是表达式 e 的潜在结果集合中的一个元素,其中左值到右值的转换(4.1)应用于 e,或者 e 是丢弃值表达式(第 5 条)。 this is odr-used if it appears as a potentially-evaluated expression (including as the result of the implicit transformation in the body of a non-static member function (9.3.1)).[...]
如果它作为潜在评估的表达式出现(包括作为非静态成员函数 (9.3.1) 的主体中的隐式转换的结果),则 this 被使用。[...]
So str_
yield a constant expression, the lvalue-to-rvalue conversion is not applied the expression str_.size()
and it is not a discarded value expression, so it is odr-used and therefore str_
is required to be defined.所以
str_
产生一个常量表达式,左值到右值的转换没有应用表达式str_.size()
并且它不是丢弃值表达式,因此它是 odr-used ,因此需要定义str_
。
On the other hand the lvalue-to-rvalue conversion is applied to the expression str_.size_
, so it is not odr-used and does not require str_
to be defined.另一方面,左值到右值的转换应用于表达式
str_.size_
,因此它不是 odr 使用的,也不需要定义str_
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.