From: DeMarcus on 15 Mar 2010 13:28 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 15 Mar 2010 19:42 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 15 Mar 2010 19:42 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 15 Mar 2010 19:45 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 15 Mar 2010 20:05
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! ] |