15

It's so easy to forget to mark a constructor "explicit": adding/removing args, making them optional etc. the single reliable way I know is to declare every constructor as explicit and then remove this keyword only if implicitness is required by design (thanks to the standard that allows this not only on single-argument constructors). But this would look ugly.

not intended implicit constructors open usage of (mistaken) implicit conversion, e.g. as here. this can happen by accident, or can break backward compatibility

so why "explicit" is not default characteristic of a constructor if this would lead to fewer bugs?

p.s. yeah, I read Stroustrup's "The Design and Evolution of C++", just don't remember if he says anything about "explicit" there

Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112
  • "forgetting" goes away with experience – Gene Bushuyev Jan 05 '11 at 17:32
  • 3
    @Gene: As does, perhaps, the desire to `explicit` everything in sight. – John Dibling Jan 05 '11 at 17:35
  • @robin hood: Regarding your link, in my view the problem there is not with implicit conversion, but with a stupid programmer who "did not know that function only takes an A object and that an A object will be created each time through the loop." If the problem is surprising code effects, then the answer must be to be a better programmer, rather than dumbing-down the language. Of course, the C#/Java/VB fans of the world may have a different opinion. – John Dibling Jan 05 '11 at 17:50
  • 1
    If constructors are `explicit` by default, then there is no way to implicitly typecast a type to a class, for example casting `const char*` to `std::string`. What mechanism would you use to restore this functionality, or would you simply disallow implicit typecasts? I, for one, like being able to declare `void foo(std::string& param);` and then call it with `foo("Testing");` instead of `foo(std::string("Testing"));`. Same with routines taking complex numbers which I would like to default to simply `0.0` or `1.0`. – Mike DeSimone Jan 05 '11 at 17:55
  • 3
    @Mike: probably I explained wrong, I was curious why C++ doesn't have "implicit" keyword that marks implicit constructors when all others are explicit by default – Andriy Tylychko Jan 05 '11 at 17:58
  • 3
    @John Dibling: The surprising effects of implicit conversion are non-local, and can be very difficult to track down. I had to track down an implicit conversion bug once after my friend gave up all hope of finding it, and though an understanding of the significance of single-argument constructors let me find it in the end, it sure took long enough. I would argue that good programmers try to minimise their vulnerability to errors, including their own, so making single-argument constructors explicit by default is a good rule of thumb. – John Bartholomew Jan 05 '11 at 17:58
  • 1
    @John: Same thing has happened to me as well. I agree that good programmers try to minimize their own errors. One way of doing that, I suppose, is to throw away the tools that cause you difficulty. I can see how that's a valid approach -- but it's not my approach. – John Dibling Jan 05 '11 at 18:14
  • 1
    @John: it's just a first example I found, not the best one, agreed – Andriy Tylychko Jan 05 '11 at 18:15
  • If you wish, you could achieve this behavior by using a code style analysis tool and adding a rule to it that verifies that all constructors are explicit, with an exception for those having a specific comment why they are implicit – Roman L Jan 05 '11 at 19:20
  • 7
    @John Dibling: I don't think this is a case of throwing away a tool. No one is saying "the language shouldn't provide a way of defining implicit conversions". Just that it's dangerous to make implicit conversions the default (requiring an extra keyword to disable it), instead of the other way round. – John Bartholomew Jan 05 '11 at 19:23
  • 6
    I found in Bjarne Stroustrup's PPP book him saying that it's a pity that constructors are not explicit by default. so you do have a point there. – MasterMastic Jun 28 '12 at 12:57

3 Answers3

15

Backward compatibility at the time when explicit was added. The language was evolving and changing meaning of existing constructs in an evolving language is a sure way to make your users angry. It is still the case now, backward compatibility is something high in the mind of the comittee.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
12

Because when C++ was conceived it was considered that nobody would write stupid code, and everybody would enjoy the benefits that nice implicit conversions would bring in avoiding having to write casts everywhere.

Of course, this turned out to be false, and really there are buggy constructors all over the place. Such a shame.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 6
    +1 I think this sums it up for me. Then the question becomes what to do about programmers writing stupid code? Many seem to be of the opinion that the language should be made simpler, so that stupid programmers can't write stupid code. My opinion is that it's better to make the programmers smarter though. Better programmers write better programs. – John Dibling Jan 05 '11 at 17:56
  • There are many valid reasons to want an explicit constructor other than having defective constructors. Writing it off as stupid code is incorrect. – edA-qa mort-ora-y Jan 05 '11 at 18:02
  • @edA-qamort-ora-y: I don't recall saying that code using explicit constructors is "stupid". You have misinterpreted my words as being simpler than they are. I said that implicit conversions were made the "default" out of fear of stupid code. That does not mean that all code not using them is stupid. – Lightness Races in Orbit Jan 06 '11 at 01:48
  • ... seems me similar to why `override` was introduced that late ... – Wolf Nov 06 '19 at 14:48
3

Interesting vantage point. I would tend to take the other side, and wonder why you think you need to mark all your constructors explicit until proved otherwise?

Honestly I don't know the answer to your question, if there even is one. Backwards compatibility seems like it might be a contender for most-likely-reason, but again: why do you wish to prevent implicit conversion?

John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • 6
    Implicit conversion sometimes results in surprising program behavior. I wish I could remember a good example. I find it more helpful than harmful in most cases. – Mark Ransom Jan 05 '11 at 17:36
  • 4
    Type matching is important in C++ for such things as expression legality and overload resolution, and a non-`explicit` constructor is a type converter for those purposes. If, for example, you have `A::A(B b)` and `foo(A a)` declared, then `B b; foo(b);` becomes legal, and that's often what you'd like to have flagged as an error. The automatic conversions can force surprising choice of overloaded functions, and anything that surprises is bad. Generally, C++ programmers seem to be agreeing more and more that implicit type conversion is bad. – David Thornley Jan 05 '11 at 17:39
  • 1
    because this opens not intended usage of (mistaken) implicit type conversion, e.g. as here: http://en.allexperts.com/q/C-1040/2010/2/C-Implicit-Conversion.htm. this can happen by accident, or can break backward compatibility. modified original post to include this example – Andriy Tylychko Jan 05 '11 at 17:43
  • 4
    @Mark: I find that typically implicit conversion results in "suprising" behavior because of errors in the surrounding code, not in the converted type itself. – John Dibling Jan 05 '11 at 17:44
  • 4
    @David: Well then I guess I maintain a minority opinion. I don't find implicit conversion bad at all. What I do find bad is when lazy programmers write sloppy code that evokes "suprising" behavior in implicit conversions. – John Dibling Jan 05 '11 at 17:46
  • 2
    @John: A code construct that hides problems in surrounding code isn't ideal for that reason. I personally don't always write correct code on the first try, and it's useful to find errors quickly. – David Thornley Jan 05 '11 at 17:50
  • @David: If you meerly sometimes write incorrect code, then you're fortunate. Personally, I almost never write correct code the first time through. I still want implicit conversion though. – John Dibling Jan 05 '11 at 17:53
  • @John: it's not just laziness, at least in my particular case. I want my code to look nice, so I don't mark any constructor as "explicit" by default, only those with single non-optional parameter. then I change signature and need to check explicitness. not a big deal for sure, but another small mine on C++ field – Andriy Tylychko Jan 05 '11 at 17:54
  • 2
    Sometimes just a very costly execution path is the surprising behaviour. You can quickly end up with code that does conversion like A => B => C => D => C => B => A (long function chains of implicit conversion). – edA-qa mort-ora-y Jan 05 '11 at 18:04
  • @wilhelmtell: good point to compare compiler errors and runtime errors. I'd prefer compiler ones, because I see them immediately and can fix myself instead of to pass to users of my code – Andriy Tylychko Jan 05 '11 at 18:12
  • @edA: The case you mention is probably one of the more frequent situations when I do use `explicit`. +1 for good point. – John Dibling Jan 05 '11 at 18:16
  • @edA: You know that you may have maximum one user-defined implicit conversion in a sequence and max two standard conversions? – Gene Bushuyev Jan 05 '11 at 18:39
  • 1
    @Gene, I know. I'm referring to the situation where functions call each other passing a parameter around. Every function takes a different, but convertible parameter. – edA-qa mort-ora-y Jan 05 '11 at 18:43