From: DeMarcus on
Hi,

I try to implement a simplified version of Alexandrescu's
Loki::SingletonHolder. See
http://loki-lib.sourceforge.net/html/a00670.html
row 717.

My code looks like this.

template<typename T>
class Singleton
{
public:
static T& getInstance()
{
return *instance_;
}

private:
typedef volatile T* SPtr;
static SPtr instance_;
};

template<typename T>
typename Singleton<T>::SPtr Singleton<T>::instance_;

int main()
{
typedef Singleton<int> S;
S::getInstance() = 4711;
}

But when I compile it with gcc 4.4.1 I get the following error message
at 'return *instance_;'.
"error: invalid initialization of reference of type 'int&' from
expression of type 'volatile int' "

What am I doing wrong?


Thanks,
Daniel


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Ulrich Eckhardt on
DeMarcus wrote:
> template<typename T>
> class Singleton
> {
> public:
> static T& getInstance()
> {
> return *instance_;
> }
>
> private:
> typedef volatile T* SPtr;
> static SPtr instance_;
> };
[...]
> S::getInstance() = 4711;
[...]
> But when I compile it with gcc 4.4.1 I get the following error message
> at 'return *instance_;'.
> "error: invalid initialization of reference of type 'int&' from
> expression of type 'volatile int' "

The compiler is telling you exactly what you do wrong. Imagine you exchanged
the "volatile" against a "const", what would you expect? Similarly, a simple
"const_cast<int&>(*instance_)" will convince the compiler for you.

Further:
1. You wouldn't need the template stuff for this example. Makes getting some
things right more complicated.
2. Your instance_ pointer is never initialized.
3. The exact semantics of volatile differ by compiler, the standard only
requires that it behaves similarly to const in above aspect (CV-qualifier).
4. If you had written "T volatile*" instead of "volatile T*", you could use
the same schema (CV-qualifier binding to the left) when creating a volatile
pointer (T* volatile) instead of a pointer to volatile, which I guess is
what you wanted actually.

Uli


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Joshua Maurice on
On Mar 15, 9:28 pm, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> Hi,
>
> I try to implement a simplified version of Alexandrescu's
> Loki::SingletonHolder. Seehttp://loki-lib.sourceforge.net/html/a00670.html
> row 717.
>
> My code looks like this.
>
> [...]
>
> What am I doing wrong?

Well, for starters, why are you using the volatile keyword? Do you
think it's a portable threading construct? It's not. volatile in C and
C++ has nothing to do with threading. The C and C++ standards do not
talk about threads, so anything they say about volatile is irrelevant.
By POSIX, volatile means nothing special for threading. (The Microsoft
compiler under certain versions does claim to make it like a mutex
acquire and release, but let's just ignore this bad form for now. Use
boost or ACE or some portable library if you need atomic functions, or
wait for the new C++ standard. At worst, wrap volatile yourself to not
litter your code with a not portable construct + usage.)

To answer your specific question, why that error message, let's look
at your code:

> template<typename T>
> class Singleton
> {
> public:
> static T& getInstance()
> {
> return *instance_;
> }
> private:
> typedef volatile T* SPtr;
> static SPtr instance_;
> };

*instance is an lvalue of type "volatile T". A "T&" cannot bind to an
lvalue of type "volatile T". A "volatile T&" can bind to an lvalue of
type "volatile T". It's basic const correctness, or more generally CV
(const volatile) correctness. The compiler won't let you assign a non-
volatile reference to a volatile lvalue, just like it won't let you
assign a non-const reference to a const lvalue.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: eca on
On Mar 16, 5:28 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:

> I try to implement a simplified version of Alexandrescu's
> Loki::SingletonHolder. Seehttp://loki-lib.sourceforge.net/html/a00670.html
> row 717.

I would suggest:

static volatile T& getInstance()
{
return *instance_;
}

"volatile", as well as "const", cannot be neglected.
BTW, remember to initialize instance_ somewhere.

HTH,
eca


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Johannes Schaub (litb) on
DeMarcus wrote:

> Hi,
>
> I try to implement a simplified version of Alexandrescu's
> Loki::SingletonHolder. See
> http://loki-lib.sourceforge.net/html/a00670.html
> row 717.
>
> My code looks like this.
>
> template<typename T>
> class Singleton
> {
> public:
> static T& getInstance()
> {
> return *instance_;
> }
>
> private:
> typedef volatile T* SPtr;
> static SPtr instance_;
> };
>
> template<typename T>
> typename Singleton<T>::SPtr Singleton<T>::instance_;
>
> int main()
> {
> typedef Singleton<int> S;
> S::getInstance() = 4711;
> }
>
> But when I compile it with gcc 4.4.1 I get the following error message
> at 'return *instance_;'.
> "error: invalid initialization of reference of type 'int&' from
> expression of type 'volatile int' "
>
> What am I doing wrong?
>
>

"T&" designates the type "int&" , but "*instance" is an expression of type
"volatile int". You cannot refer to a volatile object by a non-volatile
expression. If you do nontheless by casting away volatile, behavior is
undefined. The compiler guards you from that by not allowing the non-
volatile reference to bind to expressions of volatile type.

I dunno what Alexandrescu's code is doing, but surely there are more levels
of indirections in his code that care for health :)

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]