Solved QFlags and static functions
-
I'm trying to use QFlags with some static functions and get these unexpected linker errors.
Error LNK2001 unresolved external symbol "public: static class QFlags<enum MyTestClass::Day> MyTestClass::workweek" (?workweek@MyTestClass@@2V?$QFlags@W4Day@MyTestClass@@@@A) Error LNK2001 unresolved external symbol "public: static class QFlags<enum MyTestClass::Day> MyTestClass::weekend" (?weekend@MyTestClass@@2V?$QFlags@W4Day@MyTestClass@@@@A)
Here's the class declaration
#include <QtCore/QFlags> class DM2_DATA_API MyTestClass { public: MyTestClass() = default; ~MyTestClass() = default; enum Day { Mo = 0x01, Tu = 0x02, We = 0x04, Th = 0x08, Fr = 0x10, Sa = 0x20, Su = 0x40 }; Q_DECLARE_FLAGS(Mask, Day); static Mask DefaultWorkweek(); static Mask DefaultWeekend(); static void SetDefaultWorkweek(Mask); static void SetDefaultWeekend(Mask); static Mask workweek; static Mask weekend; }; Q_DECLARE_OPERATORS_FOR_FLAGS(MyTestClass::Mask)
and the class is implemented like this
MyTestClass::Mask workweek = MyTestClass::Mo | MyTestClass::Tu | MyTestClass::We | MyTestClass::Th | MyTestClass::Fr; MyTestClass::Mask weekend = MyTestClass::Sa | MyTestClass::Su; MyTestClass::Mask MyTestClass::DefaultWorkweek() { return workweek; } MyTestClass::Mask MyTestClass::DefaultWeekend() { return weekend; } void MyTestClass::SetDefaultWorkweek(Mask m) { workweek = m; } void MyTestClass::SetDefaultWeekend(Mask m) { weekend = m; }
The class export declaration
DM2_DATA_API
expands to this:#ifdef DM2_DATA_EXPORTS #define DM2_DATA_API __declspec(dllexport) #else #define DM2_DATA_API __declspec(dllimport) #endif
I should mention that the above class was just whipped up to demonstrate the issue.
Does anyone have any idea why the two compilation errors occur? I have two other static functions that also work with the same QFlags typedef, but they don't access the static variables of the class. Those other two functions do not cause any issues. Neither does the static member variable initialization.
I'm using MSVC 2017 and Qt 5.12.5.
Thanks in advance for any input.
-
@marcbf said in QFlags and static functions:
MyTestClass::Mask workweek = MyTestClass::Mo | MyTestClass::Tu | MyTestClass::We | MyTestClass::Th | MyTestClass::Fr;
MyTestClass::Mask weekend = MyTestClass::Sa | MyTestClass::Su;This declares 2 variables with the same name in the global scope. It should be:
MyTestClass::Mask MyTestClass::workweek = MyTestClass::Mo | MyTestClass::Tu | MyTestClass::We | MyTestClass::Th | MyTestClass::Fr; MyTestClass::Mask MyTestClass::weekend = MyTestClass::Sa | MyTestClass::Su;
-
@marcbf
From my self-admittedly sketchy knowledge of C++: where you defineworkweek
&weekend
in the class implementation, don't you have to put in thestatic
?static MyTestClass::Mask workweek = MyTestClass::Mo | MyTestClass::Tu | MyTestClass::We | MyTestClass::Th | MyTestClass::Fr; static MyTestClass::Mask weekend = MyTestClass::Sa | MyTestClass::Su;
-
@JonB Thanks for the suggestion. It's not something you normally do (the variables are already declared static in the class declaration and are merely initialized in the source file). I tried it regardless just to have exhausted that option as well. Didn't change a thing unfortunately.
-
@marcbf
Hmm, when I wrote C++ if I wrotestatic
in the header declaration I made the definition have the matchingstatic
....The error message is telling you it is expecting to find a
public static ... MyTestClass::workweek
defined (rather than declared), but it is not finding those variables.... -
@JonB I've never needed to do that (and it didn't work either). As for the variable definition, it's in the source file (the first two lines of the implementation):
MyTestClass::Mask workweek = MyTestClass::Mo | MyTestClass::Tu | MyTestClass::We | MyTestClass::Th | MyTestClass::Fr; MyTestClass::Mask weekend = MyTestClass::Sa | MyTestClass::Su;
I did make a small boo-boo, though. I forgot to put the variable declarations in the protected section and can't seem to be able to edit the original post.
Like I wrote, variable initialization etc. works as expected. It's those two functions that cause the errors, but I cannot figure out why.
-
@marcbf
Yes, I respect what you say about not needing thestatic
.
I know those two lines should be the definition in the implementation.
I am just saying that the linker errorunresolved external symbol
means that it is not "finding" them.... -
@marcbf said in QFlags and static functions:
MyTestClass::Mask workweek = MyTestClass::Mo | MyTestClass::Tu | MyTestClass::We | MyTestClass::Th | MyTestClass::Fr;
MyTestClass::Mask weekend = MyTestClass::Sa | MyTestClass::Su;This declares 2 variables with the same name in the global scope. It should be:
MyTestClass::Mask MyTestClass::workweek = MyTestClass::Mo | MyTestClass::Tu | MyTestClass::We | MyTestClass::Th | MyTestClass::Fr; MyTestClass::Mask MyTestClass::weekend = MyTestClass::Sa | MyTestClass::Su;
-
@VRonin
Ahh, of course! They need theMyTestClass::
prefix! C++ for you :) I will remember this for the future....How does this relate to the "plain"
return workweek;
statement inMyTestClass::DefaultWorkweek()
? You are saying this resolves in existing code (since it compiles OK) to the global variable, but with the change it would resolve to the static class variable? No! From the error it always resolves toMyTestClass::workweek
, one would have to have written::workweek
to resolve to the global one? -
@VRonin said in QFlags and static functions:
@marcbf said in QFlags and static functions:
MyTestClass::Mask workweek = MyTestClass::Mo | MyTestClass::Tu | MyTestClass::We | MyTestClass::Th | MyTestClass::Fr;
MyTestClass::Mask weekend = MyTestClass::Sa | MyTestClass::Su;This declares 2 variables with the same name in the global scope. It should be:
MyTestClass::Mask MyTestClass::workweek = MyTestClass::Mo | MyTestClass::Tu | MyTestClass::We | MyTestClass::Th | MyTestClass::Fr; MyTestClass::Mask MyTestClass::weekend = MyTestClass::Sa | MyTestClass::Su;
@VRonin D'oh! You nailed it! And exposed me for the utter fool that I am! :-)
I must admit, that the thought hadn't even crossed my mind, since uninitialized static variables usually throw heaps of errors, and here they didn't.
Thanks both to you and to @JonB for suffering my idiocy! And for the help as well, of course.
-
@JonB said in QFlags and static functions:
it always resolves to MyTestClass::workweek, one would have to have written ::workweek to resolve to the global one?
Correct