![]() |
|
|
Welcome to the { mindfrost82.com } forums. You are currently viewing our boards as a guest which gives you limited access to view most discussions and access our other features. By joining our free community you will have access to post topics, communicate privately with other members (PM), respond to polls, upload content and access many other special features. Registration is fast, simple and absolutely free so please, join our community today! If you have any problems with the registration process or your account login, please contact contact us. |
|
|||||||
![]() |
|
|
LinkBack | Thread Tools | Search this Thread | Display Modes |
|
|||
|
Problem with Singleton template (2)
Hi
Further to my previous post (which hasn't passed the moderator yet) I have a problem with a template Singleton class. My goal is to derive a list template from my Singleton template, and then to derive various types of list from the list template. My problem is that the compiler complains that the derived list class cannot see the Singleton's instance method. Here is a very cut down presentation of my code (with the finer points of the Singleton missing for clarity): template <typename T> class Singleton { public: static T* instance() { if (mp_instance == 0) // First time call? mp_instance = new T; // Yes: create sole instance return mp_instance; } etc. } template <class T> class MyList : public Singleton< MyList<T> > { friend class Singleton<MyList>; private: MyList() {}; ~MyList() {}; etc. } class IntList : public MyList<int> { }; I try to get a pointer to IntList: IntList* pIntList = IntList::mp_instance(); This line fails with compiler error: error: member "Singleton<T>::mp_instance [with T=MyList<int>]" is inaccessible Please can anyone suggest how to fix this? BR David -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: Problem with Singleton template (2)
I try to get a pointer to IntList:
IntList* pIntList = IntList::mp_instance(); is it a typo? I guess you meant to write IntList::instance(); about your singleton usage, err, have you thought of using specialization instead of deriving from Singleton? I think your design would be cleaner if you do something like template < class T > class MyList { ... }; class IntList: public MyList< int > { .... }; typedef Singleton< IntList > theIntList; IntList * pIntList = theIntList::instance(); // use pIntList // pIntList->foo( ); by deriving your MyList from Singleton you are forced then either to use specialization for different MyList< T > because you cannot derive further from MyList w/o up-casting the instance( ) returned value: IntList * pIntList = dynamic_cast< IntList * >( IntList::instance( ) ); //don't do this at home IntList::instance returns a MyList< int > * pointer (like pointer to base class for IntList). so, if you want an advice do not derive MyInt< T > from Singleton because instance( ) method is public static anyway so you don't need access to Singleton methods; instead use typedefs for the MyList singletons you need. typedef Singleton< DoubleList > theDoubleList; do not forget to initialize static data members for each Singleton specialization (if you don't derive from Singleton). if, for unscrutable purposes, you still want to derive from Singleton remember that further derivation is not recommendable. a parametrized (template) Singleton class usually have one purpose, to allow any class to be used as a singleton class: class A { ... } typedef Singleton< A > theA; best. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: Problem with Singleton template (2)
Hi best
Thanks very much for your reply. You were right, the compiler error was just my mis-typing. Sorry about that but I really appreciated your answer. As you predicted, my implementation failed because of the need to up-cast the instance pointer. So I am now trying to implement your suggestion. Here's an outline of my current code: template <typename T> class Singleton { public: static T* instance() { if (mp_instance == 0) mp_instance = new T; <<========= Line 48 return mp_instance; } ... private: static T* mp_instance; }; template <class T> class MyList { friend class Singleton<MyList>; .... } class IntList : public MyList<int> { }; <<======= Line 26 typedef Singleton< IntList > theIntList; main() { theIntList* ptheIntList = theIntList::instance(); <<======= Line 31 int length = ptheIntList->getListLength(0,0); } Now I get the following compiler errors: line 26: error: "MyList<T>::MyList() [with T=int]" is inaccessible detected during: implicit generation of "IntList::IntList()" at line 48 of "Singleton.h" instantiation of "T *Singleton<T>::instance() [with T=IntList]" at line 31 line 31: error: a value of type "IntList *" cannot be used to initialize an entity of type "theIntList *" Please can you suggest a fix for the errors? I can't see what is wrong. Do I need to make Singleton a friend of MyList as shown above? Thanks again for your help. David -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: Problem with Singleton template (2)
hi David,
you need to make Singleton a friend of MyList if you want to keep MyList constructors hidden (private or protected). second error you get comes from theIntList* ptheIntList = theIntList::instance(); where you try to assign a pointer to IntList to a pointer to a Singleton< IntList >. that line should be: IntList * pIntList = theIntList::instance(); understand that theIntList::instance( ) is your (hopefully) unique IntList instance. theIntList is a type of (a specialization of) Singleton that creates (by demand) a unique instance of IntList. by looking at your code I would think you're not familiar with boost libs or if you are you don't want to include some boost libs in this project. keep in mind that latest boost libs come with a somehow simplified meyer singleton implementation. I say simplified because it doesn't come with creation and destruction policies so you can't control its lifecycle (nor creation type) although I suspect it's enough for your project. also there is a boost::noncopyable base class and some other things that can solve your issues (for example boost::function_requires to check type passed to Singleton agains DefaultConstructibleConcept). singletons, although a simple idiom, proved themselves hard to implement in a complete, optimized and flexible way in C++ because mainly the language doesn't allow to us to tell compilers not to optimize a code block. there are good implementations floating around but there is always a tradeoff between simplicity, speed and flexibility. what I'm trying to say is for example std::vector, std::string and boost::smart_ptr are widely used and accepted but there is no widely used and accepted singleton template I know of. back to your project it looks to me that you want to use a singleton template to create different unique instances on a single base class hierarchy. and it also seems that you want to prevent users from instantiating your base class template and derived classes directly (if this requirement refers to base class only you can remove the friend singleton declaration from derived and make their default constructors public. I also assumed you also don't know about or you don't want to use boost. so I put together some code for you below. the trivial singleton example is not thread safe and also doesn't come with any lifecycle or creation/destruction policy. I just wanted to show you how a class hierarchy can be used together with a singleton, that's it. I tested the code with mingw/gcc. cheers, Gil /* * test_single.cpp * * Created on: Aug 21, 2008 * Author: Gill */ #include <iostream> #include <typeinfo> //#include "boost/concept_check.hpp" using namespace std; //using namespace boost; /** * @brief example meyers singleton for David. * @warning not thread safe, if used in multithreaded process than each * single instance must be initialized (called for construction) before * spawning threads. */ template< class T > class singleton { public: static T * instance( ) { /* * types used as parameters to singleton template must be default * constructible. */ //boost::function_requires< boost::DefaultConstructibleConcept< T > >( ); static T t; return &t; } private: singleton( ); ~singleton( ); }; /* * @brief non-copy base class */ template< class T > class MyList { friend class singleton< MyList< T > >; public: virtual void foo( ) { cout << this << " this is an instance of MyList< " << typeid( T ).name( ) << " >" << endl; } protected: MyList( ) { } MyList( const MyList< T >& ) { } virtual ~MyList( ) { } }; class IntList : public MyList< int > { friend class singleton< IntList >; public: void foo( ) { cout << this << " this is an instance of IntList" << endl; } protected: IntList( ) : MyList< int >( ) { } }; class DoubleList : public MyList< double > { friend class singleton< DoubleList >; public: void foo( ) { cout << this << " this is an instance of DoubleList" << endl; } protected: DoubleList( ) : MyList< double >( ) { } }; typedef singleton< IntList > theIntList; typedef singleton< MyList< int > > theMyListInt; typedef singleton< DoubleList > theDoubleList; int main( int argc, char ** argv ) { IntList * pIntList1 = theIntList::instance( ); DoubleList * pDoubleList1 = theDoubleList::instance( ); MyList< int > * pMyListInt1 = theMyListInt::instance( );; //polymorphic dispatch from singleton instances //use base class pointer to manipulate different types of singleton //adapted leaf classes MyList< int > * pMyListInt2 = theIntList::instance( );; pIntList1->foo( ); pDoubleList1->foo( ); pMyListInt1->foo( ); pMyListInt2->foo( ); //now check the instances again IntList * pIntList2 = theIntList::instance( ); DoubleList * pDoubleList2 = theDoubleList::instance( ); pIntList2->foo( ); pDoubleList2->foo( ); return 0; } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: Problem with Singleton template (2)
On 22 Aug, 07:48, ivnic...@yahoo.com wrote:
> so I put together some code for you below. the trivial singleton > example is not thread safe and also doesn't come with any lifecycle or > creation/destruction policy. I just wanted to show you how a class > hierarchy can be used together with a singleton, that's it. Thanks for your reply and code - they were really helpful. Unfortunately, our TI DSP compiler is not fully ANSI C++ Compliant. The singleton template generates a compiler warning: static T * instance( ) { static T t; <<======== Line 52 return &t; } "../Source/Singleton.h", line 52: warning: static local variables of extern inline function are not resolved to single copy. Not ANSI C++ Compliant TI's explanation is: "Static Variables in Inline Functions: Things are even more difficult when the inline function contains a static variable. The presence of a static variable does not inhibit inlining. The ANSI standard for C++ requires the compiler to create a single instance of the static local in such a case. The TI compiler does not adhere to this part of the standard. It creates a static copy of the local variable similar to how the function itself is made static. While it rarely occurs in practice, this can cause code to execute incorrectly. If the inline function is a class member function, then the best workaround is to make the local static variable a static member variable of the class." However, it seems to me that the workaround will break the Meyers Singleton pattern. To resolve this I changed back to dynamic instantiation of the instance variable: static T * instance( ) { if (mp_instance == 0) mp_instance = new T(); return mp_instance; } private: static T* mp_instance; However, I then get a linker error: <Linking> undefined symbol first referenced in ---------------- ------------------- Singleton<T1>::mp_instance [with T1=SchedulerOpList<int>] C:\ \... error: unresolved symbols remain Please can you suggest how I can resolve this linker error? Best regards David -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: Problem with Singleton template (2)
DavidA wrote:
> Unfortunately, our TI DSP compiler is not fully ANSI C++ Compliant. > The > singleton template generates a compiler warning: > > static T * instance( ) > { > static T t; <<======== Line 52 > return &t; > } > "../Source/Singleton.h", line 52: warning: static local variables of > extern > inline function are not resolved to single copy. Not ANSI C++ > Compliant > > TI's explanation is: > <snip> > However, it seems to me that the workaround will break the Meyers > Singleton > pattern. To resolve this I changed back to dynamic instantiation of > the > instance variable: > > static T * instance( ) { > if (mp_instance == 0) mp_instance = new T(); > return mp_instance; > } > > private: > static T* mp_instance; This is only a declaration of mp_instance. It is not a definition, so no storage is reserved. For a declaration, you should add the lines template <class T> static T* Singleton<T>::mp_instance; after the class definition. However, given how your compiler handles function-local statics, it may also fail to treat this correctly, as here the compiler is also required to merge multiple copies of the same template instantiation in multiple translation units into a single instance. If your compiler can not properly handle this, your options are basically down to some hack work. The easiest hack, but also a maintenance nightmare, is like this (boilerplate and error checking omitted): --- singleton.h --- void force_singleton_instances(); template <class T> class Singleton { public: static T * instance( ) { if (mp_instance == 0) mp_instance = new T(); return mp_instance; } // other members... private: friend void force_singleton_instances(); static T* mp_instance; }; --- singleton.cpp --- #include "singleton.h" template <class T> static T* Singleton<T>::mp_instance; void force_singleton_instances() { Singleton<type1>::mp_instance = Singleton<type1>::mp_instance; Singleton<type2>::mp_instance = Singleton<type2>::mp_instance; // and so on for all Singleton instances } ---- Then you just have to make sure that force_singleton_instances() is referenced somewhere in the program. The trick is that the compiler sees only one definition of Singleton<T>::mp_instance, but it is still forced to instantiate the template member for all instances. > However, I then get a linker error: > > <Linking> > > undefined symbol first > referenced in > ---------------- > ------------------- > Singleton<T1>::mp_instance [with T1=SchedulerOpList<int>] C:\ > \... > > error: unresolved symbols remain > > Please can you suggest how I can resolve this linker error? > > Best regards > > David > Bart v Ingen Schenau -- a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq c.l.c FAQ: http://c-faq.com/ c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/ [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: Problem with Singleton template (2)
On 30 Aug, 16:28, Bart van Ingen Schenau <b...@ingen.ddns.info> wrote:
> The easiest hack, but also a maintenance nightmare, is like this > --- singleton.cpp --- > #include "singleton.h" > > template <class T> > static T* Singleton<T>::mp_instance; Sadly, the compiler complains about the above declaration: "... error: a storage class may not be specified here I think I'm just going to have to give up on a Singleton template under this compiler. { In short: drop "static" from the definition of the member. -mod/sk } David -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: Problem with Singleton template (2)
On Sep 1, 3:46 pm, DavidA <dandbn...@talktalk.net> wrote:
> On 30 Aug, 16:28, Bart van Ingen Schenau <b...@ingen.ddns.info> wrote: > > > The easiest hack, but also a maintenance nightmare, is like this > > --- singleton.cpp --- > > #include "singleton.h" > > > template <class T> > > static T* Singleton<T>::mp_instance; > > Sadly, the compiler complains about the above declaration: > > "... error: a storage class may not be specified here > > I think I'm just going to have to give up on a Singleton template > under this compiler. { Edits: quoted mod comment, signature and clc++m banner removed. -mod } before giving up so easy:), why don't you try to define the static pointer in your cpp file like this: in some header you have: typedef MyList< int > IntList_t; typedef MyList< double > DoubleList_t; in your .cpp, where you first call the instance() on a type, let's say int list: IntList_t * Singleton< IntList_t >::mp_instance_ = 0L; in your .cpp file where you first call instance() on let's say DoubleList: DoubleList_t * Singleton< DoubleList_t >::mp_instance_ = 0L; I think even your compiler should swallow this because you tell it now exactly what type of static member you want to initialize and you even tell it where to put ut (in which translation unit). it seems to me that your compiler cannot expand template <class T> static T* Singleton<T>::mp_instance; to used types so you will have to specifically tell it what specializations of Singleton are you going to use like in: DoubleList_t * Singleton< DoubleList_t >::mp_instance_ = 0L; cheers, gil -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: Problem with Singleton template (2)
On Aug 28, 1:53 pm, DavidA <dandbn...@talktalk.net> wrote:
> Unfortunately, our TI DSP compiler is not fully ANSI C++ Compliant. > The singleton template generates a compiler warning: > > static T * instance( ) > { > static T t; <<======== Line 52 > return &t; > } > "../Source/Singleton.h", line 52: warning: static local variables of > extern inline function are not resolved to single copy. Not ANSI C++ > Compliant Can't you just make the instance() method not inline? template <typename T> class Singleton { public: static T* instance(); //etc. }; template <typename T> T* Singleton<T>::instance() { static T t; return &t; } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
![]() |
|
| Thread Tools | Search this Thread |
| Display Modes | |
|
|