Connecting Tech Pros Worldwide Forums | Help | Site Map

Instansing singleton right in the header file

Raider
Guest
 
Posts: n/a
#1: Mar 17 '06
I need to have one object for each template argument(s) used. For
example, I need to have one object of int. I tried the following code
and it gives me all I want with Visual C++ 7.1. But is it portable???
Will all compilers produce code that prints "single"?

Instancing of object right in header file (that can be include multiple
times - i.e. in multiple cpp files) give rise to my doubts...


Singleton.cpp
----------------------
#pragma once
template <typename T>
class Singleton
{
public:
static T * GetInstance()
{
static T Instance;
return &Instance;
}
};


First.cpp
----------------------
#include <iostream>
#include "Singleton.h"

void * First()
{
return Singleton<int>::GetInstance();
}

void * Second();

int main()
{
std::cout << (First() == Second() ? "single" : "multiple" );
std::cout << std::endl;
return 0;
}


Second.cpp
----------------------
#include <iostream>
#include "Singleton.h"

void * Second()
{
return Singleton<int>::GetInstance();
}


Victor Bazarov
Guest
 
Posts: n/a
#2: Mar 17 '06

re: Instansing singleton right in the header file


Raider wrote:[color=blue]
> I need to have one object for each template argument(s) used. For
> example, I need to have one object of int. I tried the following code
> and it gives me all I want with Visual C++ 7.1. But is it portable???[/color]

Of course.
[color=blue]
> Will all compilers produce code that prints "single"?[/color]

All compliant ones will.
[color=blue]
> Instancing of object right in header file (that can be include multiple
> times - i.e. in multiple cpp files) give rise to my doubts...[/color]

You're not instantiating it "in header file". You're instantiating it
in a function. By the time the function is generated, compiled, and
then executed, there are no header files (reminds me of "there is no
spoon" from the Matrix movie).
[color=blue]
> Singleton.cpp
> ----------------------
> #pragma once
> template <typename T>
> class Singleton
> {
> public:
> static T * GetInstance()
> {
> static T Instance;
> return &Instance;
> }
> };
>
>
> First.cpp
> ----------------------
> #include <iostream>
> #include "Singleton.h"
>
> void * First()
> {
> return Singleton<int>::GetInstance();
> }
>
> void * Second();
>
> int main()
> {
> std::cout << (First() == Second() ? "single" : "multiple" );
> std::cout << std::endl;
> return 0;
> }
>
>
> Second.cpp
> ----------------------
> #include <iostream>
> #include "Singleton.h"
>
> void * Second()
> {
> return Singleton<int>::GetInstance();
> }
>[/color]

V
--
Please remove capital As from my address when replying by mail
mlimber
Guest
 
Posts: n/a
#3: Mar 17 '06

re: Instansing singleton right in the header file


Raider wrote:[color=blue]
> I need to have one object for each template argument(s) used. For
> example, I need to have one object of int. I tried the following code
> and it gives me all I want with Visual C++ 7.1. But is it portable???
> Will all compilers produce code that prints "single"?
>
> Instancing of object right in header file (that can be include multiple
> times - i.e. in multiple cpp files) give rise to my doubts...[/color]

Absent the export keyword (which itself is not very portable at the
moment), templates *must* be defined in the header file. The
compiler/linker will make sure there is actually only one instance in
the the final product.
[color=blue]
> Singleton.cpp
> ----------------------
> #pragma once[/color]

Non-standard. Prefer #ifndef include guards.
[color=blue]
> template <typename T>
> class Singleton
> {
> public:
> static T * GetInstance()
> {
> static T Instance;
> return &Instance;
> }
> };[/color]

You might consider returning a reference and disabling some other
functions just for safety:

private:
Singleton();
Singleton( const Singleton& );
Singleton& operator=( const Singleton& );
Singleton* operator&();
~Singleton();
[color=blue]
> First.cpp
> ----------------------
> #include <iostream>
> #include "Singleton.h"
>
> void * First()
> {
> return Singleton<int>::GetInstance();
> }
>
> void * Second();
>
> int main()
> {
> std::cout << (First() == Second() ? "single" : "multiple" );
> std::cout << std::endl;
> return 0;
> }
>
>
> Second.cpp
> ----------------------
> #include <iostream>[/color]

Unnecessary here.
[color=blue]
> #include "Singleton.h"
>
> void * Second()
> {
> return Singleton<int>::GetInstance();
> }[/color]

Cheers! --M

Axter
Guest
 
Posts: n/a
#4: Mar 17 '06

re: Instansing singleton right in the header file


Raider wrote:[color=blue]
> I need to have one object for each template argument(s) used. For
> example, I need to have one object of int. I tried the following code
> and it gives me all I want with Visual C++ 7.1. But is it portable???
> Will all compilers produce code that prints "single"?
>
> Instancing of object right in header file (that can be include multiple
> times - i.e. in multiple cpp files) give rise to my doubts...
>
>
> Singleton.cpp
> ----------------------
> #pragma once
> template <typename T>
> class Singleton
> {
> public:
> static T * GetInstance()
> {
> static T Instance;
> return &Instance;
> }
> };
>
>
> First.cpp
> ----------------------
> #include <iostream>
> #include "Singleton.h"
>
> void * First()
> {
> return Singleton<int>::GetInstance();
> }
>
> void * Second();
>
> int main()
> {
> std::cout << (First() == Second() ? "single" : "multiple" );
> std::cout << std::endl;
> return 0;
> }
>
>
> Second.cpp
> ----------------------
> #include <iostream>
> #include "Singleton.h"
>
> void * Second()
> {
> return Singleton<int>::GetInstance();
> }[/color]

The code is not portable because it's using #pragma once instead of
standard header guards.
I'm guessing that Singleton.cpp is a typo, since it should be
Singleton.h

If you have a limitted set of types you want to use with your Singleton
template class, there is a way to put the implementation inside a *.cpp
file (even if you don't have export keyword support).
You can do template forward declaration.
Example:
//Your Singleton.cpp
template Singleton<int>;
template Singleton<std::string>;
#include "foofoo.h"
template Singleton<foofoo>;
//Your Singleton implementation here


If you have the above code in the Singleton.cpp file, than you can
create an instance of your Singleton template of type int, std::string,
or foofoo.
If you used a different type, than you would get a linker error.
This method is only usefull if you're only going to support limitted
types for your Singleton template.

Closed Thread