Thread: Singleton template problem

  1. #1
    Registered User
    Join Date
    Oct 2004
    Posts
    100

    Singleton template problem

    Hi all,

    I've implemented my own singleton pattern using templates for my classes to derive from. Here is a very cut down version of my code:

    Code:
    // THIS FILE IS SINGLETON.H
    
    template <typename T>
    class Singleton
    {
    public:
        static T* CreateSingleton( )
        {
            if (m_Instance == NULL)
                m_Instance = new T ; // ERROR HERE
            return m_Instance ;
        }
    private:
        static T* m_Instance ;
    };
    
    // initialize instance to NULL
    template<typename T>
    T* Singleton<T>::m_Instance = NULL ;
    the above is the singleton file, as I said it is only a snippet of the code.

    This is how you derive from the singleton class
    Code:
    #include "Singleton.h"
    
    class MyClass : public Singleton<MyClass>
    {
    };
    And this is how you use it

    Code:
    #include "MyClass.h"
    
    int main( )
    {
        MyClass* mc = MyClass::CreateSingleton( ) ;
        return 0 ;
    }
    Now I have seen code like this all over the internet and people seem to be using it fine. However when I try to compile it in g++ I get an error in Singleton.h on the line that says

    Code:
    m_Instance = new T ;
    The error is "undefined type MyClass". Now I completely understand this error because the singleton class is trying to "new" an instance of type T. However because I havent included "MyClass.h" at the top of "Singleton.h" it doesnt know about the class MyClass. For obvious reasons I dont want to add that to Singleton.h

    Now im usually fine with this kind of stuff so im putting it down to im having a blonde day. But for the life of me I cannot find away around this problem, and whats more confusing is that other people are using this technique with no issues.

    Thanks for any help

  2. #2
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    You didn't post enough code. The code you posted compiles fine with G++, as I expected.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    The only reason this doesn't compile for me is because NULL is a macro and you need to include some header for it.

    Incidentally, the macro defines NULL as 0, so you might just use 0 instead and not include anything.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by anon View Post
    The only reason this doesn't compile for me is because NULL is a macro and you need to include some header for it.

    Incidentally, the macro defines NULL as 0, so you might just use 0 instead and not include anything.
    It's generally better style in C++ to use "0" instead of "NULL" anyway.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    IMO its better to use NULL, particularly for pointers, since that indicates tot eh reader that the field is more or less 'unused', rather than passed a value of zero instead of some other possibly valid value. Generally code written to accept pointers changes it behavior when passed NULL, but that migth not be obvious if you use 0, since a lot of code has active states that use 0, such as passing the index into an array.

    I believe NULL is defined in windows.h along with a lot of other useful macros, if you are writign for linux you can just add -

    Code:
    #define NULL 0

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    windows.h might define NULL, but the proper place for it in C++ is <cstddef>.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by abachler
    IMO its better to use NULL, particularly for pointers, since that indicates tot eh reader that the field is more or less 'unused', rather than passed a value of zero instead of some other possibly valid value. Generally code written to accept pointers changes it behavior when passed NULL, but that migth not be obvious if you use 0, since a lot of code has active states that use 0, such as passing the index into an array.
    On the other hand, this can be misleading since a mistake could cause one to pass NULL where an integer, not a pointer, is expected, and the compiler would happily accept it since NULL is indeed 0. We'll just have to wait for nullptr to save us.

    Quote Originally Posted by abachler
    I believe NULL is defined in windows.h along with a lot of other useful macros
    It might be, but the correct C++ standard header is <cstddef>.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    windows.h might include cstddef.h, I haven't read through it recently.

    From teh compilers standpoint it doesnt matter, but contextually it makes the code easier to understand when I see NULL, I know immediately, ok that variable isnt important in this call. Whereas if I see 0, I have to keep it in mind. Then again, I have worked on code where a pointer to memloc 0 was a valid pointer, so if i saw a function call that refernced address 0 it was actually intended to modify that memory, whereas a cvalue of NULL lets me know that it does not intend to use it.
    Last edited by abachler; 01-10-2009 at 12:47 PM.

  9. #9
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    On the other hand, GCC defines NULL to be __null, which is basically the integer constant 0, but will emit a warning if it is actually used as an integer. So NULL does have its advantages.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Which is why I agree with abachler. Use NULL for pointers, not 0.
    I think it is pretty safe to guess that almost every header actually includes cstddef, or defines NULL itself. However, it might not be as good as thing to rely on.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Only stdlib.h/cstdlib and stdio.h/cstdio are guaranteed to define NULL, besides stddef.h/cstddef of course. No other header guarantees availability of the macro.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #12
    Registered User
    Join Date
    Oct 2004
    Posts
    100
    Thanks all for the reply,

    I had a bit of a jiggle around with the code and I managed to get the exact same code spitting out another error which was "undefined reference to vtable".

    I understand what the vtable is but I have never come across this error with the microsoft compiler only g++.

    The gcc faq mentions the following:


    The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined, but does not require any diagnostic for violations of this rule [class.virtual]/8. Based on this assumption, GCC will only emit the implicitly defined constructors, the assignment operator, the destructor and the virtual table of a class in the translation unit that defines its first such non-inline method.

    Therefore, if you fail to define this particular method, the linker may complain about the lack of definitions for apparently unrelated symbols. Unfortunately, in order to improve this error message, it might be necessary to change the linker, and this can't always be done.

    The solution is to ensure that all virtual methods that are not pure are defined. Note that a destructor must be defined even if it is declared pure-virtual [class.dtor]/7.
    When I define the virtual methods in the cpp file I get an "undefined reference to vtable". However when I define the methods with the declaration in the header file, everything compiles.

    I have never used g++ so its probably me just missing something but surely you're not expected to define all the virtual members in the header files?

    The IDE im using is codeblocks.

    Thanks again

  13. #13
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I can't see what all the virtual things has to do with Singleton that consists entirely of static things. May-be you could post your new code?
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  14. #14
    Registered User
    Join Date
    Oct 2004
    Posts
    100
    Unfortunately I dont have access to the code at the moment (I can get it again tomorrow).

    The issue seems to be that the classes deriving from the Singleton pattern all have a virtual destructor (because they are deriving publicly from the singleton class).

    If you look at the singleton code I posted above there is an extra function declared like so:

    Code:
    public :
     virtual ~Singleton( ) { }
    this is obviously the destructor and as you can tell it is inlined.

    Now the code compiles fine if I also define the derived classes destructors inline like the singleton class. However if I define them in the cpp file and not the header file then I get this "unreference vtable" error.

    Hopefully that makes sense.

    Thanks again for your help

  15. #15
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Make the destructor non-virtual and protected, not virtual and public. There's absolutely no reason for it to be public or virtual.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. template class problem
    By l2u in forum C++ Programming
    Replies: 4
    Last Post: 02-13-2008, 02:10 PM
  2. im extreamly new help
    By rigo305 in forum C++ Programming
    Replies: 27
    Last Post: 04-23-2004, 11:22 PM
  3. Prime Number Generator... Help !?!!
    By Halo in forum C++ Programming
    Replies: 9
    Last Post: 10-20-2003, 07:26 PM
  4. include question
    By Wanted420 in forum C++ Programming
    Replies: 8
    Last Post: 10-17-2003, 03:49 AM
  5. Problem with template usage
    By rmullen3 in forum C++ Programming
    Replies: 2
    Last Post: 02-23-2002, 06:30 PM