Copy Constructor DIP and implementation

Jonathan M Davis newsgroup.d at jmdavisprog.com
Tue Sep 25 03:05:47 UTC 2018


On Monday, September 24, 2018 7:59:36 PM MDT Nicholas Wilson via 
Digitalmars-d-announce wrote:
> On Monday, 24 September 2018 at 23:22:13 UTC, Jonathan M Davis
>
> wrote:
> > @implicit on copy constructors is outright bad. It would just
> > be a source of bugs. Every time that someone forgets to use it
> > (which plenty of programmers will forget, just like they forget
> > to use @safe, pure, nothrow, etc.), they're going to have a bug
> > in their program. However, unlike, with attributes like @safe
> > or pure, they're not going to get a compiler error in their
> > program; they're going to get a logic error. They may or may
> > not find that bug quickly, but the compiler isn't going to
> > point it out to them.
>
> I think this is the most important reason. In C++, where
> everything is implicit by default (which is bad) and (I think)
> you are encouraged to use explicit where possible, you should
> never use it for the copy constructor because the compiler always
> calls it implicitly for you and is the whole point of having:
>
> Foo a; Foo b = a;
>
> do something useful. Putting explicit on the copy ctor means that
> no longer works, one can then only use it with
>
> Foo a; Foo b(a);
>
> Having `Foo a; Foo b = a;` do something completely different by
> the addition or removal of one attribute is a serious problem
> just waiting to happen.

The key thing with explicit in C++ is to avoid issues with implicit
conversions between types. You can get weird junk like where

int foo(string s);

foo(42);

compiles, because you have a type A with an implicit constructor which takes
int, and an implicit conversion to string. Even though A isn't explicitly
used here anywhere, because it's available, and no more than three
conversions are required to go from int to string when using A, the compiler
will use A to from int to string. That probably isn't what the programmer
wanted, but the compiler will happily do it.

Because of this, it's best practice in C++ to put explicit on any
constructors which take other types where you don't explicitly want the
implicit conversion in order to try to avoid this conversion mess. You then
only leave explicit off of constructors where you want the implicit
conversion or constructors where it's unnecessary (e.g. default constructors
or copy constructors). D avoids this mess by simply not having any kind of
implicit construction. It just has implicit conversion via alias this. It
may or may not be worth adding implicit construction via something like
@implicit, but it would at least then only be on constructors which were
explicitly marked with @implicit, whereas with C++, you have to use explicit
to turn off the behavior. So, in C++, it's a total mess by default, whereas
in D, we'd only have it where the programmer asked for it. And presumably,
any DIP that added it wouldn't have the compiler do more than one conversion
at a time, whereas as I understand it, C++ allows the compiler to do up to
three conversions in order to make a piece of code work. But ultimately,
such details will have to be decided with such a DIP.

Either way, none of this has anything to do with copy constructors. It makes
no sense to have copy constructors that require that you call them
explicitly. And while it would be bad enough if the DIP required that you
mark copy constructors with @implicit for them to work as copy constructors
and then didn't have implicit copying without @implicit, that's not what it
does. Instead, what it does when you forget @implicit is revert to the
default copy semantics, meaning that you have a copy constructor that needs
to be called explicitly, but you didn't realize that it needed to be called
explicitly, and you're blindly using the default copy semantics rather than
the copy constructor. So, the semantics that the DIP describes are just
plain a recipe for bugs. But since the PR has been updated to remove
@implicit, maybe the DIP will be updated to remove it as well, and the whole
@implicit discussion can be left to a future DIP on implicit construction
and left out of copy construction entirely.

- Jonathan M Davis





More information about the Digitalmars-d-announce mailing list