I was curious as to why the C++ standards board/the guy who made C++ decided to make all non default constructors non explicit? Stroustrup said that with C you shoot yourself in the foot, but with C++ you blow your foot off... Why didn't they make all non default constructors explicit so that you cannot make a silly error such as a comparison operator with an object to, say an integer, which could cause garbage answers. Why not make it that if you want non explicit constructor you use the keyword

nonEeplicit constructorName(int a);

it would make allot of sense, and it would also cause an error if the user tried to compare the object incorrectly.

As I understand it, the explicit keyword is only useful on a single-argument constructor, because they can be either implicit or explicit, but any other constructor is explicit.

There are two (2) ways to declare an object. First, you can do this:

someType anObject(someValue);

or you can do this:

someType anObject = someValue

The first version is called an "explicit" declaration. The second version is called an "implicit" declaration, and it can only be done with a single-argument constructor.

When you apply the explicit keyword to a constructor, you disallow the implicit version of the declaration.

Edited 5 Years Ago by Fbody: n/a

What I mean is... Why did has the standards committee kept them non explicit, wouldn't it make sense to change them to by default be explicit?

That's what I'm saying. Except for a single-argument constructor, which can be either explicit or implicit depending on whether or not the explicit keyword was used, they are explicit.

Look at it this way. If you have an int variable, how do you most commonly declare and initialize it? Like this:

int someIntVar = 5;

If all constructors were explicit, you wouldn't be able to do that, you would have to do this instead:

int someIntVar(5);

It's the implicit nature of the single-argument constructor that allows you to perform the declaration and initialization in a single statement using the assignment operator. The single-argument constructor is also the only one you can do this with. If you have a multi-argument constructor, it is automatically explicit. Take an example class:

class Sample {
 private:
   int PrvInt1;
   int PrvInt2;
 public:
   Sample() : PrvInt1(0), PrvInt2(0) {}                     //default constructor
   Sample(int incoming) : PrvInt1(incoming), PrvInt2(0) {}  //single-argument constructor
   Sample(int in1, int in2) : PrvInt1(in1), PrvInt2(in2) {} //multi-argument constructor
}; //end class definition

If you were to create an instance of this class, you have 4 ways to do it:

Sample obj1;              //declare a default object
Sample obj2 = 5;          //implicitly declare a single-argument object
Sample obj3(10);          //explicitly declare a single-argument object
Sample obj4(5, 10);       //explicitly declare a multi-argument object

If you add the explicit keyword to the definition of the single-argument constructor, the statement declaring and initializing "obj2" becomes invalid.

Edited 5 Years Ago by Fbody: n/a

> wouldn't it make sense to change them to by default be explicit?

Yes, it would. If it was meditated on right at the outset, I guess the keyword would have been implicit - constructors would have been explicit by default.

However, an important consideration during standardization is that when a new feature is introduced, existing valid, well-written code should continue to work the same way. So, the keyword added was explicit - the default bahaviour is implicit, as it had been earlier.

> wouldn't it make sense to change them to by default be explicit?

Yes, it would. If it was meditated on right at the outset, I guess the keyword would have been implicit - constructors would have been explicit by default.

However, an important consideration during standardization is that when a new feature is introduced, existing valid, well-written code should continue to work the same way. So, the keyword added was explicit - the default bahaviour is implicit, as it had been earlier.

I understand your logic, but don't forget though that, the only way to call a constructor that has 2+ arguments is explicitly using operator(), you can't use operator= to imply the constructor argument(s).

I suppose you could call the default constructor's behavior implicit, but I would argue that it's neither explicit nor implicit because it's only called when you don't provide any sort of information when the object is declared. How can you be either one when there's nothing to work with? Really, the only constructor(s) that the implicit concept applies to is the single-argument, which defaults to implicit to allow custom dataTypes to behave in a fashion similar to the native types. If you add the explicit keyword it eliminates that behavior and it behaves like the rest of the constructors.

I guess I just don't understand why the OP has an issue...:)

Edited 5 Years Ago by Fbody: n/a

First, some corrections on Fbody's comments:

>>The second version is called an "implicit" declaration

No. To be accurate, (8.5/14) a syntax like int a = 42; is called a copy-initialization, and will be realized with an implicit type conversion if one exists (either as an implicit converting-constructor in the destination type or an implicit conversion operator in the source type). Moreover, (8.5/15) a syntax like int a(42); is called a direct-initialization and will be realized with a constructor of the destination type (explicit or not) and possibly needing an implicit conversion of the source type (e.g. int to double). (5.4/2) A syntax like int(42); is an explicit type conversion by means of a functional notation (as opposed to the type conversion operator (like static_cast<int>(42); ) or a cast expression (int)42; ).

>>Except for a single-argument constructor, which can be either explicit or implicit depending on whether or not the explicit keyword was used, they are explicit.

They are not explicit, because the implicit/explicit concept only applies to type conversion methods. It is only meaningful to talk about a constructor being explicit or not when you talk about a converting-constructor (12.3.1/1), all other constructors are neither implicit nor explicit, they are just not converting-constructors.

Also, to further drive home the point that implicit/explicit applies only to type conversion methods, the new standard now allows you to specify conversion operators to be explicit as well (12.3.2/2). So, implicit/explicit only applies to means of type conversions, not to constructors in general.


Now, to address the actual question: Why the converting-constructors are assumed to provide implicit conversions unless marked with the explicit keyword?

I cannot say for sure, but I highly suspect that the original motivation for having implicit converting constructors in the first place was to allow for the copy-initialization syntax on user-defined classes. But, of course, they could have allowed that by having an implicit keyword to activate that feature of implicit type conversion. But, remember that in the beginning, there wasn't much of a standard committee (let alone an actual standard), and these types of fundamental decisions had to be made to make it a programming language to start with, so the only guy who really knows why it was decided to be this way is Bjarne Stroustrup himself. And that is if it was even a conscious decision to start with or if he even thought that there would be any consequence to making converting-constructors implicit by default (this can be pretty hard to anticipate when there isn't much of a user-base or experts to consult). He's not perfect, you know.

Now that it is the way it is, then:
>> "wouldn't it make sense to change them to by default be explicit?"
No. It doesn't make sense to change something so fundamental and trigger a tsunami of backward compatibility problems for all the existing C++ code-base.

At least, now, we also have the explicit keyword working for conversion operators, and not only for converting constructors.

Of course, the only solution is to make it a strong habit to always write your converting constructors with the explicit keyword (i.e. develop it as an unconscious reflex). Then, remove the keyword to make it implicit, I have also seen some people use this syntax too:

struct my_int {
  int value;

  /*implicit*/ my_int(int aValue) : value(aValue) { };
};

The above is useful because when you or another person reviews the code and sees a converting constructor that isn't marked explicit , it should raise a red-flag, but with the above, it makes the intention explicit (pun intended!).

Comments
:( I'm getting really tired of you spouting Doctoral dissertations at me.
This article has been dead for over six months. Start a new discussion instead.