In a.hh --------- class A { static constexpr float val = 0.08; public: bool foo(const float v); }; In a.cc -------- bool A::foo(const float v) { return (v < -val); } Created a libfoo.so from the above code and linked this .so with another executable using A::foo(const float) method. Creating an executable result in "undefined reference to A::val" If I replace val with -0.08 and change foo method with return (v < val), val is getting inlined.
This is invalid as per [class.static.data]/3 : "A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. — end note ] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer."
.
(In reply to comment #1) > This is invalid as per [class.static.data]/3 : On C++11 level it should be valid, because odr-usage does not happen here according to [basic.def.odr] p3: "A variable x whose name appears as a potentially-evaluated expression ex is odr-used unless x is an object that satisfies the requirements for appearing in a constant expression (5.19) and 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)."
Let's reopen this, then.
(In reply to comment #3) > (In reply to comment #1) > > This is invalid as per [class.static.data]/3 : > > On C++11 level it should be valid http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#712 is post-C++11 but as a DR we should implement it for all values of -std
Created attachment 34147 [details] Files for testcase of initial post
Created attachment 34148 [details] second test case
The described case seems to work in GCC 4.9.2 with the attached files and g++ -c -fpic testicle.cc -std=c++11 g++ -shared -o libtesticle.so testicle.o g++ -L/home/usack/entwicklung/tetris -Wall -o testicles main.cc -ltesticle -std=c++11 However, if I add another data member which is initialized with val by default, I still get the "undefined reference" error, see second attachment.
(In reply to Juisoo from comment #8) > However, if I add another data member which is initialized with val by > default, I still get the "undefined reference" error, see second attachment. The second testcase is reduced like below. ============== testcase ============== struct A { static constexpr float val = 0.08; A(const float& = val) {} }; int main() { A{}; } ============== testcase ============== cf. http://melpon.org/wandbox/permlink/ZCbNwLlPQakWjluY I think that the testcase is ill-formed because the A::val is odr-used. When A's ctor is called with no argument, 1) The lvalue-to-rvalue conversion is not applied to A::val. (Since the ctor's parameter is a reference type.) 2) A::val is not a discarded-value expression. On the other hand, A::val is not odr-used in the first testcase. (Since the builtin unary - operator requires that its operand is a prvalue.) So, I think that this pr is fixed. (But I don't know whether this pr can be closed since I cannot find a test.)
Still an issue at gcc 5.3.0.
(In reply to Mitsuru Kariya from comment #9) > (In reply to Juisoo from comment #8) > > However, if I add another data member which is initialized with val by > > default, I still get the "undefined reference" error, see second attachment. > > The second testcase is reduced like below. > > ============== testcase ============== > struct A { > static constexpr float val = 0.08; > A(const float& = val) {} > }; > > int main() > { > A{}; > } > ============== testcase ============== > cf. http://melpon.org/wandbox/permlink/ZCbNwLlPQakWjluY You still need: constexpr float A::val;
*** Bug 113465 has been marked as a duplicate of this bug. ***
(In reply to Andrew Pinski from comment #11) > You still need: > constexpr float A::val; In C++11 mode, yes. C++17 made all static constexpr data members implicitly inline, which change the situation. Inline variables ought to be emitted on use and merged at runtime. This explanation does not change the resolution of this bug report. But if you can update your code to use -std=c++17, gnu++17 or later, then the problem goes away.