Connecting Tech Pros Worldwide Forums | Help | Site Map

forward-decl for Singleton?

Markus Dehmann
Guest
 
Posts: n/a
#1: Dec 20 '07
I need a Singleton for general program options so that all classes can
access it.

I use the code below (adapted from the Wikipedia singleton example).
But the problem is if I change one variable in it, all my classes have
to re-compile. But I am planning to add more options often during
development. I tried to solve it through a forward declaration "class
Opts;", but didn't succeed because Opts::instance() results in an
error message about the incomplete type.

One solution might be to use a key-value map, but I would prefer to
use the variables directly, because they can be accessed faster, and
all possible options are known at compile-time.

Does anyone have a hint how to do the forward decl so that I don't
have to recompile every class that includes the Opts decl whenever I
add an option?

Thanks!
Markus

// header singleton.h
template<typename Tclass Singleton{
public:
static T& Instance(){
static T theSingleInstance; // assumes T has a protected
default constructor
return theSingleInstance;
}
};

// header opts.h
class Opts : public Singleton<Opts>{
friend class Singleton<Opts>;
public:
int option1;
bool option2;
protected:
Opts(): option1(42), option2(false); // defaults
};

// opts.cc
Opts::Opts() {}

werasm
Guest
 
Posts: n/a
#2: Dec 20 '07

re: forward-decl for Singleton?


On Dec 20, 11:02 pm, Markus Dehmann <markus.dehm...@gmail.comwrote:
Quote:
I need a Singleton for general program options so that all classes can
access it.
>
I use the code below (adapted from the Wikipedia singleton example).
But the problem is if I change one variable in it, all my classes have
to re-compile. But I am planning to add more options often during
development. I tried to solve it through a forward declaration "class
Opts;", but didn't succeed because Opts::instance() results in an
error message about the incomplete type.
>
One solution might be to use a key-value map, but I would prefer to
use the variables directly, because they can be accessed faster, and
all possible options are known at compile-time.
>
Does anyone have a hint how to do the forward decl so that I don't
have to recompile every class that includes the Opts decl whenever I
add an option?
>
Thanks!
Markus
>
// header singleton.h
template<typename Tclass Singleton{
public:
static T& Instance(){
static T theSingleInstance; // assumes T has a protected
default constructor

I've written a little test to see if this works (especially this
assumption stated here above about protected default:

template <class T>
struct Base
{
static T& instance()
{
static T failToCompile;
return failToCompile;
}
};

struct Derived
{
protected:
Derived(){}
};

int main()
{
Derived& d = Base<Derived>::instance();
return 0;
}

Looks like it does not like the base attempting to call
the protected constructor in the derived. ;-)

Regards,

Werner
werasm
Guest
 
Posts: n/a
#3: Dec 20 '07

re: forward-decl for Singleton?


On Dec 20, 11:02 pm, Markus Dehmann <markus.dehm...@gmail.comwrote:

Quote:
Does anyone have a hint how to do the forward decl so that I don't
have to recompile every class that includes the Opts decl whenever I
add an option?
Someone may have a solution, but I would try to give the generic base
a clear responsibility - singleton instantiation of the applicable
derived. If options are applicable to the derived only, then it should
not be part of the singleton. I suppose the reason you want to make
it part of the singleton is because you need to instantiate each
derived with options. A couple of questions then come to mind.

- Is the type of the options unique per singleton/derived?
- If not unique, can the type of options vary.
- Can the value of options vary (is it default constructible or does
is only have static const members.

An idea might be to let the derived get its options from
a factory during its construction possible using typeid
or a string. I personally don't think it is idiomatic to
have arguments in instance. Otherwise you could possible
consider explicit creation of the singleton which
uses a non-instance method, the creation taking option
as argument.

In general the implementation of template code should be
stable as modification to it affects all translation units
that use it. If this is not the case, I think the unstable
code should be moved.

Hope this helps a little.

Regards,

Werner

Markus Dehmann
Guest
 
Posts: n/a
#4: Dec 21 '07

re: forward-decl for Singleton?


On Dec 20, 5:38 pm, werasm <wer...@gmail.comwrote:
Quote:
On Dec 20, 11:02 pm, Markus Dehmann <markus.dehm...@gmail.comwrote:
>
Quote:
Does anyone have a hint how to do the forward decl so that I don't
have to recompile every class that includes the Opts decl whenever I
add an option?
>
Someone may have a solution, but I would try to give the generic base
a clear responsibility - singleton instantiation of the applicable
derived. If options are applicable to the derived only, then it should
not be part of the singleton. I suppose the reason you want to make
it part of the singleton is because you need to instantiate each
derived with options. A couple of questions then come to mind.
I think there is a misunderstanding. All I care about is that I can
use the Opts class anywhere (globally) in my code, using calls like
this:

// set a global value
Opts::Instance().option1 = 124;
// get a global value
if(Opts::Instance().option2){
// do something
}

That's the typical use for the singleton design pattern. I happened to
give code that implements a special Singleton class providing the
Instance() method, but I could have implemented this function directly
in the Opts class and not use inheritance.

The question is how to make calls like "Opts::Instance().option1"
possible, but with a design that allows for a forward declaration of
the class Opts, so that I can add or remove variables in the class
(like int option1, or bool option2) without having to recompile my
whole project (because many files will want to include the Opts
class.)
Quote:
- Is the type of the options unique per singleton/derived?
- If not unique, can the type of options vary.
- Can the value of options vary (is it default constructible or does
is only have static const members.
The values can vary. Any caller may set or get the public variables.
(I don't think getter and setter methods are necessary.)
Quote:
An idea might be to let the derived get its options from
a factory during its construction possible using typeid
or a string. I personally don't think it is idiomatic to
have arguments in instance. Otherwise you could possible
consider explicit creation of the singleton which
uses a non-instance method, the creation taking option
as argument.
Using a factory might be an idea ...
Quote:
In general the implementation of template code should be
stable as modification to it affects all translation units
that use it. If this is not the case, I think the unstable
code should be moved.
Yes, I don't expect the Singleton class to be modified during
development. Just the Opts class, whenever we add another option
variable (e.g. double option3;)

--Markus
anon
Guest
 
Posts: n/a
#5: Dec 21 '07

re: forward-decl for Singleton?


Markus Dehmann wrote:
Quote:
I use the code below (adapted from the Wikipedia singleton example).
But the problem is if I change one variable in it, all my classes have
to re-compile. But I am planning to add more options often during
development. I tried to solve it through a forward declaration "class
Opts;", but didn't succeed because Opts::instance() results in an
error message about the incomplete type.
>
[snip]
Quote:
>
// header singleton.h
template<typename Tclass Singleton{
public:
static T& Instance(){
static T theSingleInstance; // assumes T has a protected
default constructor
return theSingleInstance;
}
};
>
// header opts.h
class Opts : public Singleton<Opts>{
friend class Singleton<Opts>;
public:
int option1;
bool option2;
protected:
Opts(): option1(42), option2(false); // defaults
};
>
// opts.cc
Opts::Opts() {}
Search for the pImpl idiom.

It should look something like this:

// header opts.h
class Opts : public Singleton<Opts>{
friend class Singleton<Opts>;
public:
class Impl;
std::auto_ptr< Impl pImpl;
protected:
Opts(): option1(42), option2(false); // defaults
};

// opts.cc
class Opts::Impl
{
public:
Impl() {}
~Impl(){}

// add options here
}

Opts::Opts() : pImpl( new Impl )
{
}

Adding options, your interface for the class Opts does not change to
outside world, and you can easily add more options.
Bart van Ingen Schenau
Guest
 
Posts: n/a
#6: Dec 21 '07

re: forward-decl for Singleton?


On 20 dec, 23:02, Markus Dehmann <markus.dehm...@gmail.comwrote:
Quote:
I need a Singleton for general program options so that all classes can
access it.
>
I use the code below (adapted from the Wikipedia singleton example).
But the problem is if I change one variable in it, all my classes have
to re-compile. But I am planning to add more options often during
development. I tried to solve it through a forward declaration "class
Opts;", but didn't succeed because Opts::instance() results in an
error message about the incomplete type.
>
One solution might be to use a key-value map, but I would prefer to
use the variables directly, because they can be accessed faster, and
all possible options are known at compile-time.
>
Does anyone have a hint how to do the forward decl so that I don't
have to recompile every class that includes the Opts decl whenever I
add an option?
The problem is that a forward declaration will not cut it. The
compiler will never take your word for it that Opts has a particular
member unless it has seen the definition of Opts.

If you really want to access the options as members of the Opts class,
then there is no way to avoid the recompilation of all dependent code
when you add a new option variable/function.
The reason is that the build system only sees that a particular file
has changed, without knowing what kind of changes were made. To be on
the safe side, the build system assumes that an interface change has
been made that affects all dependent code, so that all has to be
rebuilt.

Quote:
>
Thanks!
Markus
>
Bart v Ingen Schenau
Closed Thread