Thread: Singleton base template class? How do you do that?!

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    58

    Singleton base template class? How do you do that?!

    So, I'm trying to create a singleton base template class so I can simulate XNA game services by allowing a class to be initialized only once, and by allowing that class to be added to a linked list of similar base objects.

    The only solution I found to this problem was to create a singleton base template class, and create a static linked list of the base class to keep track of the services.



    ...This is proving to be more of a problem than anything, and here is why:


    Singleton.h
    Code:
    template <class T>
    class Singleton 
    {
    public: 
    	~Singleton(void) {};
    	static T& GetService(void) {return *Instance;}
    protected:
    	Singleton<T>(void) {};
    	static T* Instance;
    };
    ApplicationManager.h
    Code:
    #include "application.h"
    #include "singleton.h"
    class ApplicationManager : public Singleton<ApplicationManager>
    {
    public:
    	Application* ActiveApplication(void) {return _ActiveApplication;}
    	~ApplicationManager(void);
    private:
    	ApplicationManager(void);
    	ApplicationManager(Application* app);
    	Application* _ActiveApplication;
    };


    The line in my main method:
    Code:
    ApplicationManager Prog = ApplicationManager::GetService();
    The above line gives me the following external error:

    LNK2001: unresolved external symbol "protected: static class ApplicationManager *Singleton<class ApplicationManager>::Instance"



    What I was trying to do here, was to simply pass a single copy of the class into ApplicationManager prog.


    Does anyone see the problem? Or does anyone know of a better/more elegant solution to this?

  2. #2
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    You need to initialize the static member, eg:

    Code:
    template <class T>
    class Singleton 
    {
    public: 
    	~Singleton(void) {};
    	static T& GetService(void) {return *Instance;}
    protected:
    	Singleton<T>(void) {};
    	static T* Instance;
    };
    
    template <class T>
    T* Singleton<T>::Instance = 0;
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    And just a little food for thought:

    Code:
    template < typename Class >
    struct Singleton
    {
        Singleton( void )
        {    
            if( instance_ )
                throw; // or what have you...
            instance_ = ( Class* )this;    
        }
    
        static inline Class& instance( void )
        {
            return *instance_;
        }
        
        static inline bool exists( void )
        {
            return instance_ != 0;
        }
        
        virtual ~Singleton( void )
        {
            instance_ = 0;    
        }
        
        protected:
            
        static Class* 
            instance_;
    };
    
    template < typename Class >
    Class* 
        Singleton< Class >::instance_ = 0;
    And then:

    Code:
    /*
        What the client code sees
    */    
    class ApplicationManager : public Singleton<ApplicationManager>
    {
    public:
        ~ApplicationManager(void)
        {    }
        
        virtual void foo( void ) = 0;
        
    protected:
        
        ApplicationManager(void)
        {    }
    };
    
    
    /*
        The *real* implementation
    */
    class MyApplicationManager : public ApplicationManager
    {
    public:    
    
        MyApplicationManager(void)
        {    }
        
        virtual void foo( void )
        {
            cout << "MyApplicationManager" << endl;
        }
    };
    
    MyApplicationManager
        mgr_;
    And from the client code:

    Code:
    int main( void )
    {
        ApplicationManager::instance( ).foo( );
    }
    The point is, you don't have to fool with wierd allocation schemes if you don't want to, and you can reassign the singleton by allowing the current one to go out of scope, or if it was dynamically allocated, deleted first. But at any rate the client code doesn't have to worry about how the singleton is managed internally - the code stays the same for them.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    Registered User
    Join Date
    Apr 2008
    Posts
    58
    Wow...thank you guys for the feedback! I just realized I did some funky things haha

    Good call on the struct, and virtual functions btw! I like that a lot!

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    class and struct are mostly the same.
    Sebastiani simply uses structs due to personal preference.
    You can use classes if you want. Classes have private visibility by default and struct have public by default. That's all there is to it.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  2. Creating a database
    By Shamino in forum Game Programming
    Replies: 19
    Last Post: 06-10-2007, 01:09 PM
  3. help with template class using a template node
    By aciarlillo in forum C++ Programming
    Replies: 11
    Last Post: 06-02-2005, 05:46 PM
  4. Operator overloading in template classes
    By moejams in forum C++ Programming
    Replies: 5
    Last Post: 07-21-2003, 05:16 PM
  5. Replies: 4
    Last Post: 12-29-2002, 12:29 AM