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