class B : public A {
B(const B& other);
public:
explicit B(){}
};
int main() {
A const & a = B(); // L1
A a2 = B(); // L2
}
Why VC++ 2010 and g++ give error related to private copy constructor
in 'B' in Line L2. I understand the Line L1 is governed by $8.5.3/5 (C+
+ 2003)
Dabs.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
A diagnostic is required in C++03, because it is implementation-
defined whether the rvalue is directly bound or whether a copy of
that rvalue is directly bound. Note that the first bullet in 8.5.3/5 does
not really apply, because the first sub-bullet is not satisfied (the
initializer expression is no lvalue) nor is any implicit conversion
taking place here. Therefore we end in the second bullet of that
paragraph:
"Otherwise, the reference shall be to a non-volatile const type (i.e.,
cv1 shall be const)."
The spec proceeds:
"— If the initializer expression is an rvalue, with T2 a class type, and
“cv1 T1” is reference-compatible with “cv2 T2,” the reference is bound
in one of the following ways (the choice is implementation-defined):
— The reference is bound to the object represented by the rvalue
(see 3.10) or to a sub-object within that object.
— A temporary of type “cv1 T2” [sic] is created, and a constructor
is called to copy the entire rvalue object into the temporary. The
reference is bound to the temporary or to a sub-object within the
temporary.93)
The constructor that would be used to make the copy shall be callable
whether or not the copy is actually done."
As of C++0x, direct-binding to the initial object is required and this
program is well-formed given the new spec.
HTH & Greetings from Bremen,
Daniel Krügler
There is no problem here B() just creates a temporary B object and binds
it to a reference to A. Of course as the classes are not polymorphic the
result is a complete waste of time because the only behaviour you can
get for a2 is the behaviour of an A.
> A a2 = B(); // L2
Quite different. First a B object is constructed, then it is copied and
finally sliced (of course in the absence of any data members slicing is
trivial) to fit the A destination. However it is the copy that is sliced
and though the copy process can (and almost always will be) elided the
compiler must first check that the copying can be done. In this case it
cannot.
> }
>
> Why VC++ 2010 and g++ give error related to private copy constructor
> in 'B' in Line L2. I understand the Line L1 is governed by $8.5.3/5 (C+
> + 2003)
>
--
The compiler is allowed to copy the temporary created by B(). To be
consistent for all compilers, the language rules says that there must
be an accessible copy constructor, whether the object is copied or
not.
I believe this rule will be removed in C++0x. Seems like no compilers
will actually copy anything here.
Bo Persson
But the C++ standard states
"in a return statement in a function with a class return type, when
the expression is the name of a
non-volatile automatic object with the same cv-unqualified type as the
function return type, the copy
operation can be omitted by constructing the automatic object directly
into the function’s return value"
Here the type of the destination is 'A' and is not the same as 'B'. So
why does copy constructor elision come into picture?
Dabs.
Anubhav wrote:
> > class A {
> > };
> >
> > class B : public A {
> > B(const B& other);
> > public:
> > explicit B(){}
> > };
> >
> > int main() {
> > A const & a = B(); // L1
> > A a2 = B(); // L2
> > }
> >
> > Why VC++ 2010 and g++ give error related to private copy constructor
> > in 'B' in Line L2. I understand the Line L1 is governed by $8.5.3/5
> > (C+ + 2003)
> >
> > Dabs.
>> The compiler is allowed to copy the temporary created by B(). To be
>> consistent for all compilers, the language rules says that there must
>> be an accessible copy constructor, whether the object is copied or
>> not.
>>
>> I believe this rule will be removed in C++0x. Seems like no compilers
>> will actually copy anything here.
>>
>
> But the C++ standard states
>
> "in a return statement in a function with a class return type, when
> the expression is the name of a
> non-volatile automatic object with the same cv-unqualified type as the
> function return type, the copy
> operation can be omitted by constructing the automatic object directly
> into the function’s return value"
This has no relevance to the code above as no functions are being called.
>
>
> Here the type of the destination is 'A' and is not the same as 'B'. So
> why does copy constructor elision come into picture?
The process is:
1) create a temporary B object
2) Use that to initialise the A constructor. As the A constructor needs
a value of type A the temporary B object is notionally copied (and the
code above does not allow that copy because the copy ctor has been
declared as private) and then the B part is sliced off to leave just an
A value which is used to initialise a2.
Now you may consider that to be pretty pedantic and no doubt the
moajority of WG21 agree with you which is why they have changed the
rules that apply to this kind of definition with an initialiser but
until the new standarf is released compilers in fully conforming mode
are required to issue a diagnostic.