Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 define workweek & weekend in the class implementation, don't you have to put in the static?

    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 wrote static in the header declaration I made the definition have the matching static....

    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 the static.
    I know those two lines should be the definition in the implementation.
    I am just saying that the linker error unresolved 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 the MyTestClass:: prefix! C++ for you :) I will remember this for the future....

    How does this relate to the "plain" return workweek; statement in MyTestClass::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 to MyTestClass::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


Log in to reply