Topic: confused about 'explicit' copy-constructor and 'return


Author: jpotter@falcon.lhup.edu (John Potter)
Date: 3 Sep 2001 17:26:47 GMT
Raw View
On 28 Aug 2001 10:29:19 -0400, jpotter@falcon.lhup.edu (John Potter)
wrote:

Replying to my own post because I am not sure whether Gabriel has
accepted my point or just lost interest.  I am interested in
understanding this, not being right.  I have cross-posted to csc++
and set followups there which seems appropriate for this part
of the thread.

Explicit copy ctor prevents copy initialization, is the question.

> On 27 Aug 2001 08:53:53 -0400, Gabriel Dos Reis
> <dosreis@cmla.ens-cachan.fr> wrote:

> > jpotter@falcon.lhup.edu (John Potter) writes:

> > | The use of the term explicit
> > | with a copy ctor is nonsense because a copy ctor is never used in an
> > | implicit conversion.

> > I think it helps to recall what "implicit conversion" means:

> > 13.3.3.1/3
> >    Except in the context of an initialization by user-defined conversion
> >    (13.3.1.4, 13.3.1.5),

> Most of this discussion is about 13.3.1.4.

[other standard references snipped]

> > Given that, I don't agree with you that a copy-constructor is never
> > used in an implicit conversion.

> Maybe I just lack imagination.  I can't see any case where a compiler
> would select a copy ctor which performs no conversion to do a
> conversion.  Could you give an example where it is?  So that we don't
> get confused, here is the non-example again.

> struct Int {
>    int i;
>    Int (int i = 0) : i(i) { }
>    Int (Int const& src) : i(i.src) { }
>    };
> Int i1 = 42;

> This is a copy-initialization by user defined conversion.  The
> conversion sequence is Int(42) resulting in an Int.  The copy ctor
> is then used to direct initialize i1.  The copy ctor is explicitely
> required by the definition of copy initialization.  It is not part
> of the conversion sequence.  There is only one implicit user defined
> conversion because the copy ctor is explicitly required.  Am I
> misreading 13.3.1.4 or 8.5?

> If I have that right, I find it inconsistent that the standard uses
> explicit to prevent copy-initialization where the copy ctor is
> neither implicit nor part of a conversion sequence.

Maybe it is only inconsistent in common sense not in law.  It clearly
states that an explicit ctor may only be used with the direct *syntax*
or a cast.  What seems inconsistent to me is that explicit was created
to prevent implicit conversions.  The standard does not say that though.

Here is an example which may meet my request.

struct B {
    B () { }
//  explicit
    B (B const&) { }
    };
struct D : B {
    };
struct A {
//  explicit
    A (B) { }
//  explicit
    A (A const&) { }
    };
int main () {
    D d;
    A a1 = d; // A(A(B(d)))
    A a2 = a1; // A(a1)
    }

The outer A is required by copy initialization.  The next is the user
defined conversion from B to A.  The inner is the construction of the
B via copy ctor following the derived to base conversion, or may be
a part of it.  There is no derived to base standard conversion, it
just happens to references magicly.  This seems to be a copy ctor
used in an implicit conversion.  None of them use the direct syntax.

The other one is copy initialization with direct semantics, but not
direct syntax.  [8.5/14]

Since the copy ctor is a user defined conversion ctor, it seems that
there are three implicit user defined conversions in one initialization.
I can rationalize that by noting that the outer copy ctor is explicit
in copy initialization and the inner is explicit in the derived to
base conversion.  Is that what happens?  The alternative is that a copy
ctor does not perform a conversion because there is no identity
conversion.  That seems to contradict the wording of the standard.

Four compilers reject the statement when the second ctor is explicit.
Three reject it when the first is explicit.  One rejects it and the
following statement when the third ctor is explict.  I suspect that
the rejection in all three cases is conforming.  I can also agree with
the three which consider the copy ctor in copy initialization explicit.
I can also see the point of the one which also accepts the copy ctor
in the other case.

Any rational for the rule, whatever it is?  Was it designed or did it
just fall out of the wording by accident?

John

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]