C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Problems initializing a static reference member variable

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Soulshift
Guest





PostPosted: Sun Oct 26, 2003 5:00 am    Post subject: Problems initializing a static reference member variable Reply with quote



Hi,

Given the following:

class A {
public:
A(){}
private:
A(A&){}
};

class B {
private:
static A& staticMember;
};

A& B::staticMember = A();

MSVC 6's compiler complains that it needs to access A's copy constructor:
error C2248: 'A::A' : cannot access private member declared in class 'A'

However, when I make the copy constructor public, it never gets called
anyway. Also, there doesn't seem to be a requirement for a copy constructor
in this case. Am I somehow doing this wrongly or is this yet another MSVC6
compiler bug?

Thanks,
Linus Tan



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Siemel Naran
Guest





PostPosted: Sun Oct 26, 2003 11:08 am    Post subject: Re: Problems initializing a static reference member variable Reply with quote



"Soulshift" <ltan (AT) do (DOT) not.spam.epicentrix.net> wrote in message

Quote:
class A {
public:
A(){}
private:
A(A&){}
};

class B {
private:
static A& staticMember;
};

A& B::staticMember = A();

MSVC 6's compiler complains that it needs to access A's copy constructor:
error C2248: 'A::A' : cannot access private member declared in class 'A'

However, when I make the copy constructor public, it never gets called
anyway. Also, there doesn't seem to be a requirement for a copy
constructor
in this case. Am I somehow doing this wrongly or is this yet another MSVC6
compiler bug?

Is this one of those cases where the copy constructor is required to exist,
though the compiler may optimize away calling it?

Anyway, you create a temporary A object, store the reference of it.
Remember that at the semicolon the program destroys the temporary A object.
So your reference is invalid.


--
+++++++++++
Siemel Naran


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

Back to top
Christoph Schulz
Guest





PostPosted: Sun Oct 26, 2003 3:04 pm    Post subject: Re: Problems initializing a static reference member variable Reply with quote



Hello!

Soulshift <ltan (AT) do (DOT) not.spam.epicentrix.net> wrote:

Quote:
Hi,

Given the following:

class A {
public:
A(){}
private:
A(A&){}
};

class B {
private:
static A& staticMember;
};

A& B::staticMember = A();

MSVC 6's compiler complains that it needs to access A's copy
constructor: error C2248: 'A::A' : cannot access private member
declared in class 'A'

However, when I make the copy constructor public, it never gets called
anyway. Also, there doesn't seem to be a requirement for a copy
constructor in this case. Am I somehow doing this wrongly or is this
yet another MSVC6 compiler bug?

First, initializing a non-const reference with a temporary is
not valid C++. Because the expression "A()" creates an (unnamed)
temporary object, this object can only be bound to a "const A &"
(in your example).

Second, the copy constructor needs to be accessible because of
paragraph 8.5.3/5 in the standard. For details, see the thread

http://groups.google.com/groups?selm=1B097B7096652942BBF2F1ED436CC4E2052F77C8%40MSPMAILV2.retek.int

Basically, if your member was of type "const A &" and the copy-
constructor accepted a "const A &" parameter, a C++ implementation
would be allowed to bind "B::staticMember" during initialization
to a temporary which is copy-constructed from the initializer
expression. That means that "A()" would be first copied (by calling
the copy-constructor) and then "staticMember" would be bind to
that copy. The standard does not mandate the copying, but it doesn't
prohibit it either, so the copy-constructor must be accessible
at the point of reference binding.

Again, this all applies *only* to binding to const references, and
not to non-const references, as in your example.


Regards,
Christoph



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

Back to top
John Potter
Guest





PostPosted: Sun Oct 26, 2003 7:12 pm    Post subject: Re: Problems initializing a static reference member variable Reply with quote

On 26 Oct 2003 01:00:02 -0400, "Soulshift"
<ltan (AT) do (DOT) not.spam.epicentrix.net> wrote:

Quote:
class A {
public:
A(){}
private:
A(A&){}
};

class B {
private:
static A& staticMember;
};

A& B::staticMember = A();

MSVC 6's compiler complains that it needs to access A's copy constructor:
error C2248: 'A::A' : cannot access private member declared in class 'A'

However, when I make the copy constructor public, it never gets called
anyway. Also, there doesn't seem to be a requirement for a copy constructor
in this case. Am I somehow doing this wrongly or is this yet another MSVC6
compiler bug?

This is amusing. The code as written is invalid because an rvalue, A(),
may not be bound to a non-const reference. It seems that the compiler
is accepting this for way backward compatibility. If we change it to
A const& in both places, then it is valid to bind the rvalue to a const
reference, but a copy constructor is required to be callable. This is
the error you are seeing. Making the copy ctor public removes this
problem, but introduces another binding to a non-const reference because
your copy ctor does not take a reference to const. In addition to
making the ctor public, it must also take a const&. The call may be
optimized out as you saw, but it must be callable.

You could also use the rvalue to lvalue conversion of operator= to
remove the error keeping the copy ctor private and taking a reference
to non-const.

A& B::staticMember = A() = A();

Note that the first symbol '=' is the initializer syntax while the
second is the compiler generated operator=. This is equivalent to

A& B::staticMember((A() = A()));

The extra set of parens are needed to change the function declaration
to a variable definition. Now we construct two A objects, copy
assign the right one to the left one returning an A& from operator=
which is then bound to the staticMember. Now both A objects are
destructed leaving a dangling reference. But, there is no syntax
error. ;)

John

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

Back to top
John Potter
Guest





PostPosted: Sun Oct 26, 2003 7:13 pm    Post subject: Re: Problems initializing a static reference member variable Reply with quote

On 26 Oct 2003 06:08:43 -0500, "Siemel Naran"
<SiemelNaran (AT) REMOVE (DOT) att.net> wrote:

Quote:
Is this one of those cases where the copy constructor is required to exist,
though the compiler may optimize away calling it?

Yes, iff you accept the old concept of binding a non-const reference to
an rvalue.

Quote:
Anyway, you create a temporary A object, store the reference of it.
Remember that at the semicolon the program destroys the temporary A object.
So your reference is invalid.

I suspect that the backward compiler also extends the lifetime of the
temporary in the same way that it would for a const reference. It will
likely work on that compiler only and fail to compile on the later
releases or other vendors.

John

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

Back to top
Soulshift
Guest





PostPosted: Sun Oct 26, 2003 7:13 pm    Post subject: Re: Problems initializing a static reference member variable Reply with quote


"Siemel Naran" <SiemelNaran (AT) REMOVE (DOT) att.net> wrote

Quote:
"Soulshift" <ltan (AT) do (DOT) not.spam.epicentrix.net> wrote in message

class A {
public:
A(){}
private:
A(A&){}
};

class B {
private:
static A& staticMember;
};

A& B::staticMember = A();

MSVC 6's compiler complains that it needs to access A's copy
constructor:
error C2248: 'A::A' : cannot access private member declared in class 'A'

However, when I make the copy constructor public, it never gets called
anyway. Also, there doesn't seem to be a requirement for a copy
constructor
in this case. Am I somehow doing this wrongly or is this yet another
MSVC6
compiler bug?

Is this one of those cases where the copy constructor is required to
exist,
though the compiler may optimize away calling it?

Seems highly possible. I'm compiling with optimizations off though, so I'm
not sure if the compiler would do that particular optimization.

Quote:
Anyway, you create a temporary A object, store the reference of it.
Remember that at the semicolon the program destroys the temporary A
object.
So your reference is invalid.

I thought it might be as well, but oddly enough it works. In fact, I
verified that the destructor for A gets called when the program exits.

So... What's the right way to do this?

- Linus Tan



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

Back to top
John Potter
Guest





PostPosted: Sun Oct 26, 2003 11:58 pm    Post subject: Re: Problems initializing a static reference member variable Reply with quote

On 26 Oct 2003 14:13:52 -0500, "Soulshift"
<ltan (AT) do (DOT) not.spam.epicentrix.net> wrote:

Quote:
So... What's the right way to do this?

Why do you want a static reference non-object refering to an
object? The compiler will likely optimize it out since
references are not objects. You may as well have an object.

static A staticMember;
....

A B::staticMember; // is default constructed

John

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

Back to top
Siemel Naran
Guest





PostPosted: Mon Oct 27, 2003 12:02 am    Post subject: Re: Problems initializing a static reference member variable Reply with quote

"Soulshift" <ltan (AT) do (DOT) not.spam.epicentrix.net> wrote in message

Quote:
So your reference is invalid.

I thought it might be as well, but oddly enough it works. In fact, I
verified that the destructor for A gets called when the program exits.

See response by John that explains why it works.

Quote:
So... What's the right way to do this?

I'd venture for,

(1) Make a default constructed A object in an unnamed namespace.
(2) Make B::staticMember point/refer to the object.

// B.cpp
#include "B.hpp"
namespace { A a; }
A& B::staticMember = a;

--
+++++++++++
Siemel Naran


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

Back to top
Glen Low
Guest





PostPosted: Tue Oct 28, 2003 5:30 am    Post subject: Re: Problems initializing a static reference member variable Reply with quote

Quote:
Anyway, you create a temporary A object, store the reference of it.
Remember that at the semicolon the program destroys the temporary A
object.
So your reference is invalid.

I thought it might be as well, but oddly enough it works. In fact, I
verified that the destructor for A gets called when the program exits.

Hmm? According to 12.2/5, you are binding a reference to a temporary
(even though strictly speaking it should be a const reference), so it
persists for the lifetime of the reference, which in your case is
until the end of the program.

Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com

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

Back to top
Soulshift
Guest





PostPosted: Wed Oct 29, 2003 9:30 am    Post subject: Re: Problems initializing a static reference member variable Reply with quote

"John Potter" <jpotter (AT) falcon (DOT) lhup.edu> wrote

Quote:
On 26 Oct 2003 14:13:52 -0500, "Soulshift"
[email]ltan (AT) do (DOT) not.spam.epicentrix.net[/email]> wrote:

So... What's the right way to do this?

Why do you want a static reference non-object refering to an
object? The compiler will likely optimize it out since
references are not objects. You may as well have an object.

static A staticMember;
...

A B::staticMember; // is default constructed

John


Ach, that was so blindingly obvious I completely failed to realize it.
Thanks for your other informative responses as well :)

- Linus Tan



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

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.