|
-
July 24th, 2008, 07:00 AM
#1
[RESOLVED] Using boost's singleton class
I'm trying to save myself some time and use boost's singleton class instead of writing my own... but it's giving me some weird error that I can't resolve:
Code:
#include <iostream>
#include <string>
#include <map>
#include <exception>
#include "boost/shared_ptr.hpp"
#include "boost/pool/detail/singleton.hpp"
class Surface
{
public:
Surface()
{
std::cout << "Loaded a surface." << std::endl;
}
};
class Surface_Cache : public boost::details::pool::singleton_default<Surface_Cache>
{
public:
typedef boost::shared_ptr<Surface> Surface_Ptr;
typedef std::map<const std::string, Surface_Ptr> surface_cache;
typedef surface_cache::iterator cache_it;
Surface_Ptr Load_Surface(const std::string& file_name)
{
cache_it it = cache.find(file_name);
if(it == cache.end())
{ // Add surface.
Surface_Ptr s(new Surface());
cache.insert(std::make_pair(file_name, s));
return s;
}
return it->second;
}
private:
surface_cache cache;
};
int main()
{
Surface_Cache::instance().Load_Surface("example.png");
return 0;
}
Code:
1>c:\documents and settings\bill\my documents\visual studio 2005\projects\test\test\main.cpp(39) : error C2248: 'boost::details::pool::singleton_default<T>::singleton_default' : cannot access private member declared in class 'boost::details::pool::singleton_default<T>'
1> with
1> [
1> T=Surface_Cache
1> ]
1> e:\everything\programs\boost\boost\pool\detail\singleton.hpp(71) : see declaration of 'boost::details::pool::singleton_default<T>::singleton_default'
1> with
1> [
1> T=Surface_Cache
1> ]
1> This diagnostic occurred in the compiler generated function 'Surface_Cache::Surface_Cache(void)'
Why is it complaining?
Cheers.
-
July 24th, 2008, 07:25 AM
#2
Re: Using boost's singleton class
Don't know boost well enough to say, but I'm not sure this is actually saving you time if it's giving you trouble. Making a class a singleton is only about 5 extra lines of code, after all.
-
July 24th, 2008, 07:32 AM
#3
Re: Using boost's singleton class
 Originally Posted by Lindley
Don't know boost well enough to say, but I'm not sure this is actually saving you time if it's giving you trouble. Making a class a singleton is only about 5 extra lines of code, after all.
5 extra lines? Do you have an example to back that up? Haha. I thought you had to write a Singleton class and then derive your class from it?
Edit: I did it haha. It wasn't that hard after all.
Code:
#include <iostream>
#include <string>
#include <map>
#include <exception>
#include "boost/shared_ptr.hpp"
template<typename T>
class Singleton
{
public:
virtual ~Singleton() {}
static T& Instance()
{
static T object;
return object;
}
};
class Surface
{
public:
Surface()
{
std::cout << "Loaded a surface." << std::endl;
}
};
class Surface_Cache : public Singleton<Surface_Cache>
{
public:
typedef boost::shared_ptr<Surface> Surface_Ptr;
typedef std::map<const std::string, Surface_Ptr> surface_cache;
typedef surface_cache::iterator cache_it;
Surface_Ptr Load_Surface(const std::string& file_name)
{
cache_it it = cache.find(file_name);
if(it == cache.end())
{ // Add surface.
Surface_Ptr s(new Surface());
cache.insert(std::make_pair(file_name, s));
return s;
}
return it->second;
}
private:
surface_cache cache;
};
int main()
{
Surface_Cache::Instance().Load_Surface("example.png");
return 0;
}
Last edited by Mybowlcut; July 24th, 2008 at 07:50 AM.
-
July 24th, 2008, 08:36 AM
#4
Re: Using boost's singleton class
 Originally Posted by Mybowlcut
5 extra lines? Do you have an example to back that up? Haha. I thought you had to write a Singleton class and then derive your class from it?
Edit: I did it haha. It wasn't that hard after all. 
Well, you *can*, but there's no real need to. Making a class a singleton requires:
-Marking all constructors and operator= private. Even if you don't implement operator= or the copy constructor, they should be declared private to avoid auto-generating them public.
-Writing a getInstance() function.
-As far as I know, if you use the version of getInstance() with a static object (as you have), there isn't even a need for a mutex to ensure thread-safety. If you were going to use dynamic allocation instead, there would be.
-
July 24th, 2008, 08:42 AM
#5
Re: Using boost's singleton class
It´s not that easy 
You have to make sure your singleton object cannot be copied, therefore you have to make the copy constructor/assignment operator private. Or derive from boost::non_copyable.
- Guido
-
July 24th, 2008, 08:44 AM
#6
Re: Using boost's singleton class
Wait wait wait... so I make constructors, copy constructor and assignment operator private on the Singleton class? Or every class that derives from it? I'm assuming the Singleton haha.
-
July 24th, 2008, 08:51 AM
#7
Re: Using boost's singleton class
There's no need to make a Singleton class that others derive from at all. It's equally easy to just turn any old class into a singleton.
-
July 24th, 2008, 09:00 AM
#8
Re: Using boost's singleton class
 Originally Posted by Lindley
There's no need to make a Singleton class that others derive from at all. It's equally easy to just turn any old class into a singleton.
Well instead of doing it several times I thought it'd be easier to do it once and then just derive from that? But just out of curiousity, how would you turn a class into a singleton?
-
July 24th, 2008, 09:06 AM
#9
Re: Using boost's singleton class
How about
Code:
class Settings
{
public:
static Settings * Instance();
protected:
Settings ();
Settings (const Settings &);
Settings & operator= (const Settings &);
private:
static Settings * pinstance;
};
Before post, make an effort yourself, try googling or search here.
When posting, give a proper description of your problem, include code* and error messages.
*All code should include code tags
-
July 24th, 2008, 09:08 AM
#10
Re: Using boost's singleton class
I just explained it up-thread.
The problem with deriving from a singleton class is that you've still got to mark your own class uncopyable. I don't think simply declaring the base class uncopyable is good enough; you'd probably still have to declare your constructors private to avoid a compiler error (so you'd get enforcement, but no real effort savings), and I'm not sure operator= would be caught at all.
-
July 24th, 2008, 10:53 AM
#11
Re: Using boost's singleton class
All you have to do is to implement these lines of code:
Code:
class MyClass
{
public:
static MyClass& instance()
{
static MyClass theInstance;
return theInstance;
}
private:
MyClass(); // <-- must be implemented, of course
// these need to be declared, but don´t need to be implemented
MyClass( const MyClass& op );
MyClass& operator=( const MyClass& op );
};
Edit:
Added the static modifier for instance() function
Last edited by GNiewerth; July 28th, 2008 at 03:27 AM.
- Guido
-
July 24th, 2008, 12:14 PM
#12
Re: Using boost's singleton class
Why are you deriving from boost::details::pool::singleton_default? It is a simple template on the type parameter for which you should pass the type which you want to make a singleton. That is, just define your class in a normal way and use it as:
Code:
A & ref = boost::details::pool::singleton_default<A>::instance();
A being your class. However, there is a limitation to this template. It needs to have no throw default constructor for A. Now, since you would provide a default constructor and that too a public one, singleton-ness of that class cannot be mandated. You might include some logic inside your class' constructor to throw on subsequent constructor calls.
There could be another way - defining singleton_default<T> as a friend of T. That is, make:
Code:
boost::details::pool::singleton_default<A>
as a friend of A. Something like this:
Code:
#include <boost/pool/detail/singleton.hpp>
namespace bdp = boost::details::pool;
struct A{
friend class bdp::singleton_default<A>;
private:
A(){}
~A(){}
public:
void f(){ std::cout << "hello\n";}
};
int main(){
A & ref = bdp::singleton_default<A>::instance();
ref.f();
}
Don't know if it works though.
Last edited by exterminator; July 24th, 2008 at 12:18 PM.
Can you help me with my homework assignment?, Before you post!, Use code tags, How to post!, Codeguru technical FAQs, C++ FAQ Lite, Stroustrup: C++ Style and Technique FAQ, Guru of the Week, Comeau C and C++ FAQs, Comeau C++ Templates FAQs, CUJ @ DDJ, Spam threshold
My Blogs : Learning C++ is fun | Abnegator's reflections
Open Threads : C++ Aha! Moments | Nature of work in C++?
-
July 24th, 2008, 12:21 PM
#13
Re: Using boost's singleton class
As the documentation on boost says that this might be replaced soon by a boost singleton library, it might be better to wrap the singleton getInstance inside a function to localize the effect of that change on your codebase. In fact, I have seen applications that localize any usage of a 3rd party lib. Your call depending upon the effort needed.
Can you help me with my homework assignment?, Before you post!, Use code tags, How to post!, Codeguru technical FAQs, C++ FAQ Lite, Stroustrup: C++ Style and Technique FAQ, Guru of the Week, Comeau C and C++ FAQs, Comeau C++ Templates FAQs, CUJ @ DDJ, Spam threshold
My Blogs : Learning C++ is fun | Abnegator's reflections
Open Threads : C++ Aha! Moments | Nature of work in C++?
-
July 24th, 2008, 06:53 PM
#14
Re: Using boost's singleton class
 Originally Posted by exterminator
Why are you deriving from boost:  etails:: pool::singleton_default?
When there is no example usage on the internet (not even on the boost documentation page) and then you factor in my level of expertise in C++ you can see why I'd try and derive from it. After reading your post I realised I don't want to touch singleton_default haha.
 Originally Posted by Lindley
I just explained it up-thread.
The problem with deriving from a singleton class is that you've still got to mark your own class uncopyable. I don't think simply declaring the base class uncopyable is good enough; you'd probably still have to declare your constructors private to avoid a compiler error (so you'd get enforcement, but no real effort savings), and I'm not sure operator= would be caught at all.
Sorry Lindley, I should have read that.
 Originally Posted by GNiewerth
All you have to do is to implement these lines of code:
Code:
class MyClass
{
public:
MyClass& instance()
{
static MyClass theInstance;
return theInstance;
}
private:
MyClass(); // <-- must be implemented, of course
// these need to be declared, but don´t need to be implemented
MyClass( const MyClass& op );
MyClass& operator=( const MyClass& op );
};
So then you'd put functions that need to be called by code in the public section? I thought that someone would mistakingly try and call them without going through instance but then I realised that the object can't even be constructed so that won't happen haha.
Cheers for all your help!
-
July 26th, 2008, 06:16 AM
#15
Re: Using boost's singleton class
 Originally Posted by Mybowlcut
When there is no example usage on the internet (not even on the boost documentation page) and then you factor in my level of expertise in C++ you can see why I'd try and derive from it. 
You searched at all the right places except one. Considering the singleton_pool is part of the pool library, and not as an independent lib on its own, you should have looked inside boost/pool for example usage. And in fact it is being used there: singleton_pool.hpp. 
 Originally Posted by Mybowlcut
After reading your post I realised I don't want to touch singleton_default haha.
Just to clarify, I did not recommend against using it. I just provided guidelines around something that might change/or be replaced in the future.
Can you help me with my homework assignment?, Before you post!, Use code tags, How to post!, Codeguru technical FAQs, C++ FAQ Lite, Stroustrup: C++ Style and Technique FAQ, Guru of the Week, Comeau C and C++ FAQs, Comeau C++ Templates FAQs, CUJ @ DDJ, Spam threshold
My Blogs : Learning C++ is fun | Abnegator's reflections
Open Threads : C++ Aha! Moments | Nature of work in C++?
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|