Results 1 to 6 of 6

Thread: Cannot build a simple template

  1. #1
    Join Date
    Aug 2011
    Posts
    33
    Thanks
    11
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Cannot build a simple template

    I've been all over google trying to understand why I can't get this to work

    I've tried all kinds of things I've seen out there, even including the source file (ugh!) but whenever I'm not getting compiler errors, I'm getting linker errors.

    OK, maybe I'm just a rube.

    Anyway the code below is throwing this compiler exception.

    LNK2019 unresolved external symbol public: virtual __thiscall ControlGroup<class QRadioButton> .. yada ... yada ... yada

    Here is the code that declares an instance of the template in a header file.

    bits.h
    Qt Code:
    1. #include "controlgroup.h"
    2.  
    3. class Ui_bits
    4. {
    5. public:
    6. ControlGroup<QRadioButton> *pBitSize;
    7.  
    8. }
    To copy to clipboard, switch view to plain text mode 

    Here's the call that invokes the template and incurs the wrath of the linker.

    bits.cpp
    Qt Code:
    1. #include "bits.h"
    2.  
    3. void some_init_func()
    4. {
    5. Twidget tw;
    6. ui->pBitSizes = new ControlGroup <QRadioButton>(&tw, ui->centralWidget);
    7. }
    To copy to clipboard, switch view to plain text mode 

    Here is the header for the offending template class...

    controlgroup.h
    Qt Code:
    1. #ifndef CONTROLGROUP_H
    2. #define CONTROLGROUP_H
    3.  
    4. #include <QtCore>
    5. #include <QtGui>
    6.  
    7. typedef void (*pf)(int);
    8.  
    9. class Twidget
    10. {
    11. public:
    12. QString name;
    13. QSignalMapper mapper;
    14. QList <pf> slotList;
    15. int count;
    16. };
    17.  
    18. template <typename T>
    19. class ControlGroup : public QWidget
    20. {
    21. public:
    22. explicit ControlGroup(Twidget *tw, QWidget *parent=0)
    23. {
    24. init (tw, parent );
    25. }
    26. ControlGroup(){};
    27.  
    28. void init( Twidget *tw, QWidget *parent);
    29. ~ControlGroup();
    30. QList<T> widget;
    31.  
    32. private:
    33. Twidget *m_tw;
    34. QWidget *m_parent;
    35.  
    36. #include "controlgroup.cpp"
    37. };
    38.  
    39. #endif // CONTROLGROUP_H
    To copy to clipboard, switch view to plain text mode 

    ... and here's the source ...

    controlgroup.cpp
    Qt Code:
    1. #ifndef CONTROLGROUP_CPP
    2. #define CONTROLGROUP_CPP
    3.  
    4. #include "controlgroup.h"
    5.  
    6. template <typename T>
    7. void init( Twidget *tw, QWidget *parent )
    8. {
    9. for (int index = 0; index < tw->count; index++)
    10. {
    11. widget.append(new <T>(parent));
    12. }
    13. }
    14.  
    15. #endif
    To copy to clipboard, switch view to plain text mode 

    I'm sure it's something stupid, and that you guys frequently see ignorance like this.

    It's probably a face-palmer, but I just can't figure it out.

  2. #2
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Cannot build a simple template

    Qt Code:
    1. class ...
    2. private: ...
    3.  
    4. #include "controlgroup.cpp"
    5. };
    To copy to clipboard, switch view to plain text mode 
    To be honest, I've never seen anything like that before Especially that the "controlgroup.cpp" includes the file in which it is included.
    Why dont you just define the template class in one single header ? I think you can get away from your linker issues this way easily.

  3. #3
    Join Date
    Mar 2011
    Location
    Hyderabad, India
    Posts
    1,882
    Thanks
    3
    Thanked 452 Times in 435 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows
    Wiki edits
    15

    Default Re: Cannot build a simple template

    As a standard C/C++ coding practice templates have to be declared and defined in same header file.

    You can still have separate h and cpp files, in your case do the following things, it should work
    1. remove #include "controlgroup.h" from controlgroup.cpp file.
    2. all other files(.h, .cpp,...) in the project should only include "controlgroup.h", nothing should include "controlgroup.cpp" (except controlgroup.h, which you already have)

  4. #4
    Join Date
    Dec 2009
    Posts
    128
    Thanks
    7
    Thanked 14 Times in 14 Posts
    Platforms
    Unix/X11 Windows

    Default Re: Cannot build a simple template

    also, in the init() method :

    Qt Code:
    1. widget.append(new <T>(parent));
    To copy to clipboard, switch view to plain text mode 

    does not make sense. T is a type, so allocating new object is more like :

    Qt Code:
    1. widget.append(new T(parent));
    To copy to clipboard, switch view to plain text mode 


    plus, in your ControlGroup constructor, init() must be called as a templated method, so it should be :

    Qt Code:
    1. init<T>(tw, parent );
    To copy to clipboard, switch view to plain text mode 

    third, make sure you import <QRadioButton> header where you need to.

  5. #5
    Join Date
    Aug 2011
    Posts
    33
    Thanks
    11
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Cannot build a simple template

    Quote Originally Posted by totem View Post
    As a standard C/C++ coding practice templates have to be declared and defined in same header file.
    Ah! I was not aware of that. Ok, I have moved all the template stuff into the header file, both the template class declaraton and its definition. Standard practice has its reasons, and its benefits.

    Quote Originally Posted by totem View Post
    also, in the init() method :
    Qt Code:
    1. widget.append(new <T>(parent));
    To copy to clipboard, switch view to plain text mode 
    does not make sense. T is a type, so allocating new object is more like :
    Qt Code:
    1. widget.append(new T(parent));
    To copy to clipboard, switch view to plain text mode 
    OK, I fixed that. Thank you!

    Quote Originally Posted by totem View Post
    plus, in your ControlGroup constructor, init() must be called as a templated method, so it should be :
    Qt Code:
    1. init<T>(tw, parent );
    To copy to clipboard, switch view to plain text mode 
    When I did that, the compiler gave me "C2275: 'T': "Illegal use of this type as an expression.

    Quote Originally Posted by totem View Post
    third, make sure you import <QRadioButton> header where you need to.
    Yes, I have this included. In fact I have many other classes that declare instances of QRadioButton, and I have no problems. Besides, the syntax highlighter is excellent at giving you clues about whether you have your declarations and definitions going well.

    When I removed the offending <T>, even with the whole template class declaration and definition in the same from the init call, the linker still throws "2019: Unresolved externals ...".

    If I uncomment this line in the init routine, I can't even compile.
    Qt Code:
    1. widgetList.append(new T(parent));
    To copy to clipboard, switch view to plain text mode 
    This causes the compiler to emit C2664: void QList<T>::append(const T&) : cannot convert parameter1 from 'QRadioButton * to const QRadioButton const &).

    I don't know why I should get that. I declare new QRadioButtons without penalty elsewhere.

    Here is the whole controlgroup.h file as it exists now.
    Qt Code:
    1. #ifndef CONTROLGROUP_H
    2. #define CONTROLGROUP_H
    3.  
    4. #include <QtCore>
    5. #include <QtGui>
    6. #include <QtGui/QWidget>
    7. #include <QtGui/QRadioButton>
    8.  
    9. enum direction_t { go_left, go_right };
    10. typedef void (*pf)(int);
    11.  
    12. class Twidget
    13. {
    14. public:
    15. QString name;
    16. QList <QLabel> labelList;
    17. QList<QString> labelNames;
    18. QSignalMapper mapper;
    19. QList <pf> slotList;
    20. int count; // Number of widgets
    21. QRect geometry; // Size
    22. QPoint start; // Where to start the layout
    23. QPoint increment; // how to lay these out
    24. direction_t direction; // go_left or go_right
    25. };
    26.  
    27. template <typename T>
    28. class ControlGroup : public QWidget
    29. {
    30. //Q_OBJECT
    31. public:
    32.  
    33. explicit ControlGroup(Twidget *tw, QWidget *parent=0)
    34. {
    35. init(tw, parent);
    36. }
    37.  
    38. ControlGroup();
    39. ~ControlGroup();
    40.  
    41. QList<T> widgetList;
    42.  
    43. void init( Twidget *tw, QWidget *parent);
    44.  
    45. private:
    46. Twidget *m_tw;
    47. QWidget *m_parent;
    48.  
    49. };
    50.  
    51. template <typename T>
    52. void ControlGroup<T>::init( Twidget *tw, QWidget *parent )
    53. {
    54. for (int index = 0; index < tw->count; index++)
    55. {
    56. widgetList.append(new T(parent));
    57. tw->labelList.append(new QLabel(parent));
    58.  
    59. }
    60. }
    61. #endif // CONTROLGROUP_H
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Aug 2011
    Posts
    33
    Thanks
    11
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Cannot build a simple template

    Well, I got it working.

    The only thing I changed was I added empty curly brackets followed by a semicolon to the default constructor and the destructor.

    I'm still very stumped why it wouldn't link and why the error messages were so obscure. I looked them up on google, but the information was sparse and laconic.

    Thanks for all your help, though.

Similar Threads

  1. Failed to build Qt 4.7.1 in a shadow build with feature tuning
    By myfifth in forum Installation and Deployment
    Replies: 0
    Last Post: 17th February 2011, 03:25
  2. How to Install Virtual Framebuffer And Build Simple Embeded Program by QT
    By Thành Viên Mới in forum Qt for Embedded and Mobile
    Replies: 3
    Last Post: 9th November 2010, 09:14
  3. Replies: 4
    Last Post: 25th June 2010, 09:21
  4. Replies: 1
    Last Post: 13th January 2010, 23:35
  5. using the subdirs Template
    By bhs-ittech in forum Newbie
    Replies: 2
    Last Post: 23rd November 2007, 10:45

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.