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.

Go Back   { mindfrost82.com } > Gadget Corner > Tech Newsgroups > Programming > C++

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 08-20-2008, 09:58 PM
DavidA
 
Posts: n/a
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! ]

Reply With Quote
  #2 (permalink)  
Old 08-21-2008, 02:43 AM
ivnicula@yahoo.com
 
Posts: n/a
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! ]

Reply With Quote
  #3 (permalink)  
Old 08-21-2008, 09:59 PM
DavidA
 
Posts: n/a
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! ]

Reply With Quote
  #4 (permalink)  
Old 08-22-2008, 07:48 AM
ivnicula@yahoo.com
 
Posts: n/a
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! ]

Reply With Quote
  #5 (permalink)  
Old 08-28-2008, 09:53 PM
DavidA
 
Posts: n/a
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! ]

Reply With Quote
  #6 (permalink)  
Old 08-30-2008, 04:28 PM
Bart van Ingen Schenau
 
Posts: n/a
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! ]

Reply With Quote
  #7 (permalink)  
Old 09-01-2008, 08:46 PM
DavidA
 
Posts: n/a
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! ]

Reply With Quote
  #8 (permalink)  
Old 09-02-2008, 09:18 PM
ivnicula@yahoo.com
 
Posts: n/a
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! ]

Reply With Quote
  #9 (permalink)  
Old 09-02-2008, 09:21 PM
JoshuaMaurice@gmail.com
 
Posts: n/a
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! ]

Reply With Quote
Reply

  { mindfrost82.com } > Gadget Corner > Tech Newsgroups > Programming > C++


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are Off
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT. The time now is 03:59 PM.


Powered by vBulletin, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.1.0 ©2007, Crawlability, Inc.
© 1999-2008 mindfrost82.com v11.0


Sponsors:
Ringtones | Mortgages | Cheap Magazines | Wire Transfer | Credit Cards



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114