Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined reference to static const double when used with complex.h

Here's the minimum code:

#include <iostream>
#include <complex>

using namespace std;

class Test {
    static const double dt = 0.1;
public:
    void func();
};

void Test::func() {
    cout << dt << endl; // OK!
    cout << dt*complex<double>(1.0, 1.0) << endl; // Undefined reference
}

int main() {
    Test a;
    a.func();
}

The noted line gives a undefined reference to `Test::dt'. I could make a temporary variable every time I want to multiply a complex number with dt, but that is inconvenient as I am multiply many static const members with complex numbers in my code.

My guess is that when multiplying dt with a complex number, it needs, for some reason, the address of dt (i.e. &dt, which seems weird.

Any ideas why this error happens and how to make it work more elegantly than doing a double temp = dt; before every time I want to multiply it with a complex number?

like image 971
eimrek Avatar asked Aug 08 '26 09:08

eimrek


1 Answers

...how to make it work...?

#include <iostream>
#include <complex>

using namespace std;

class Test {
    static const double dt;
public:
    void func();

};

//move initialization outside of class
const double Test::dt = 0.1; 

void Test::func() {
    cout << dt << endl; // OK!
    cout << dt*complex<double>(1.0, 1.0) << endl; // Undefined reference

}

int main() {
    Test a;
    a.func();
}


OR (see this question for explanations)

class Test {
        static const double dt = 0.1;
    public:
        void func();

};
const double Test::dt;


OR (same trick as the one above has, but with c++11's constexpr)

class Test { 
         static constexpr double dt = 0.1;
    public:   
         void func();    

};                      
constexpr double Test::dt;


Any ideas why this error happens...?

From here:

If a static data member of integral or enumeration type is declared const (and not volatile), it can be initialized with a initializer in which every expression is a constant expression, right inside the class definition...

So static data member could be initialized inside of class definition if it's of the type int or enum and declared const, which isn't your case. ( see this answer for more info )

Why it's seems to be working for first line? Well, compiling with clang I got:

warning: in-class initializer for static data member of type 'const double' is a GNU extension

So this float type initialization is extension of gcc compiler, and this extension is probably won't work with function's that expecting reference type argument (just a guess for now).

Also note, that this applies to c++98 only (c++11 has constexpr keyword that is addressing this issue)

like image 122
rsht Avatar answered Aug 10 '26 21:08

rsht



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!