Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
441 views
in Technique[技术] by (71.8m points)

c++ - Strange behavior with constexpr static member variable

This is a follow up question to Undefined reference to static constexpr char[][].

The following program builds and runs fine.

#include <iostream>

struct A {
   constexpr static char dict[] = "test";

   void print() {
      std::cout << A::dict[0] << std::endl;
   }
};

int main() {
   A a;
   a.print();
   return 0;
}

However, if I change A::print() to:

   void print() {
      std::cout << A::dict << std::endl;
   }

I get the following linker error in g++ 4.8.2.

/tmp/cczmF84A.o: In function `A::print()':
socc.cc:(.text._ZN1A5printEv[_ZN1A5printEv]+0xd): undefined reference to `A::dict'
collect2: error: ld returned 1 exit status

The linker error can be resolved by adding a line:

constexpr char A::dict[];

outside the class definition.

However, it's not clear to me why using one of the members of the array does not cause a linker error while using the array causes a linker error.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The standard does not require any diagnostics for a failure to provide a definition where one is required.

3.2 One definition rule [basic.def.odr]

4 Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. [...]

This means implementations are allowed to optimise away accesses to such variables, and that's what's happening in your first case with GCC.

Both GCC and clang have decided that they prefer a consistent user experience, where error messages about missing definitions do not depend on the optimisation level. Usually, that means that any missing definition causes an error message. However, in this case, GCC is doing some minimal optimisation even at -O0, avoiding the error.

But the program is an error either way, because even A::dict[0] is an ODR-use:

3.2 One definition rule [basic.def.odr]

3 A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex 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). [...]

The use of A::dict doesn't involve lvalue-to-rvalue conversion, it involves the array-to-pointer conversion, so the exception doesn't apply.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...