Why does constexpr static member (of type type) require a definition?

==> See full snippet code and compilation on coliru .

I have a LiteralType fill class constexpr requirement :

 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)

 undefined reference to 'Foo::str_' 

I have to define constexpr static member constexpr static !
(I do not specify constructor parameters)

 constexpr MyString Foo::str_; 

However, if the constexpr static element, the constexpr static member was an int member should not be defined outside the class definition. This is my understanding, but I'm not sure ...

Questions:

  • Why doesn't int need to be defined outside the class declaration, but MyString is required for this?
  • Is there a flaw in defining constexpr static member in the header file?
    (I only provide my library as header files)
+9
source share
1 answer

One definition rule tells us that we cannot have more than one odr-used definition in a program. Therefore, if a variable is used by odr, you need to define it, but you cannot define its header file, since it can be included more than once by the whole program. Violations associated with the use of Odr do not require a diagnostic message, so you can violate this rule, and the compiler is not required to notify you.

In your case, you really use the odr use of str_ , and you cannot include the definition in the header file because it violates one definiton rule, because it can be included more than once in the program.

It is interesting to note that if you did the following, it would not be used in odr:

 return str_.size_; 

Therefore, you will not need to define a variable that may have some odd consequences in some examples . I doubt it really solves your problem in the long run.

The odr rules are described in the C ++ 3.2 draft standard section, and they say:

The variable x, whose name is displayed as a potentially evaluated expression ex, is used by odr, if the lvalue-to-rvalue transformation (4.1) is not applied to x, it gives a constant expression (5.19) that does not call any non-trivial functions and, if x is an object, ex - an element is the set of potential results of expression e, where either the lvalue-to-rvalue transformation (4.1) is applied to e or e is the expression of the reset value (paragraph 5). this is used by odr if it appears as a potentially evaluated expression (including as a result of an implicit conversion to the body of a non-static member function (9.3.1)). [...]

So str_ gives a constant expression, the lvalue-to-rale conversion does not apply the str_.size() expression and it is not the discarded value of the expression, therefore it is used as odr and therefore str_ is required to be defined.

On the other hand, the lvalue-to-rvalue transformation is applied to the str_.size_ expression, so it is not used by odr and does not require the definition of str_ .

+5
source

Source: https://habr.com/ru/post/984578/


All Articles