4

If I have a class with a constructor like this:

class A {
public:
    A(int e) {
      // Use the `e` value
    }
};

And if I make calls like this:

int main() {
  A obj = 'c';
}

What conversions would take place? Would a conversion to type A take place first, then how is it passed onto the constructor? Or would the character value be converted to int?

Also which conversions here is blocked by declaring the constructor explicit?


To clarify my doubts:

If I declare the constructor as explicit, I see these results:

int main() {
  A objA = 'x';   // Error: conversion from ‘char’ to non-scalar type ‘A’ requested
  A objA('x');    // OK
  A objA = 1;     // Error: conversion from ‘int’ to non-scalar type ‘A’ requested

  A objA = A(1);  // OK: Constructor called explicitly
  A objA = (A)1;  // OK: type Casting
}

I don't understand the behavior in the former three statements. Why do the first and third statements have conversion to A type and not to int in the first? Why does the second statement compile even though there is an implicit conversion from char to int?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Amith
  • 730
  • 6
  • 22
  • A constructor would be called with 'c' (`char`) casted to `int`. Declaring it as explicit would generate a compile time error. – Michael Chourdakis May 19 '19 at 07:03
  • @MichaelChourdakis, if i declare constuctor as explicit, the compile time error i get is `conversion from ‘char’ to non-scalar type ‘A’ requested` but only if `'c'` is assigned, not if i pass it like `A obj('c')`, then it compiles. – Amith May 19 '19 at 07:22
  • This is not an assignment, it's an initialisation. Both use the `=` symbol, but they are very different. – molbdnilo May 19 '19 at 07:31
  • Related: [What does the explicit keyword mean?](https://stackoverflow.com/q/121162) – L. F. May 19 '19 at 07:31
  • 1
    The error messages are a bit misleading (they originate from older versions of C++ where `A objA = 'x';` was defined as creating a temporary as if by `A('x')` and then initialize `objA` from the temporary) . It would be better if the message said something like "copy-initialization selected an explicit constructor" – M.M May 19 '19 at 08:28
  • @M.M According to (https://en.cppreference.com/w/cpp/language/explicit), explicit constructor cannot be used for implicit conversions, but `A objA('x');` gives no errors, is the conversion of `'x'` (`char`) to `int` is not what they are referring to? – Amith May 19 '19 at 09:17
  • @amithm7 `char` to `int` does not require any constructor – M.M May 19 '19 at 09:20
  • @M.M when is it that an implicit conversion requires a constructor? Are they referring to the conversion to `A` type from another type? – Amith May 19 '19 at 09:33
  • 1
    Conversion of `char` to class type requires a constructor. `A a('x')` is considered explicit conversion, and `A a = 'x';` is considered implicit conversion – M.M May 19 '19 at 09:35

1 Answers1

1
A obj = 'c';
A obj = 1;

These are called copy-initialization. Only converting constructors (i.e., non-explicit constructors) that accept one argument is considered in this case, with the only one being

A(int e)
{
  // ...
}

'c' (char) is converted to int and then given to the selected constructor as argument.

If you declare the constructor as explicit, then it is not a converting constructor, and copy-initialization fails to find a suitable converting constructor, making the program ill-formed.


A obj('c');
A obj{'c'}; // since C++11
A obj(1);

A(1);
(A)1;

These are called direct-initialization. All constructors (including explicit ones) are considered in this case. Therefore, regardless of whether you declare the constructor as explicit or not, the constructor is called.

M.M
  • 138,810
  • 21
  • 208
  • 365
L. F.
  • 19,445
  • 8
  • 48
  • 82
  • For explicit constructors, in case of copy-initialization, i get errors like `conversion from ‘char’ to non-scalar type ‘A’ requested`. Why is that if the conversion only happens from `char` to `int`? – Amith May 19 '19 at 08:29
  • @amithm7 Because `char` cannot be converted to `A`. It can only be converted to `int`, and `int` cannot be converted further. – L. F. May 19 '19 at 09:09
  • i only get that error when constructor is explicit. So `char` can be converted to `A` when constructor is non-explicit? – Amith May 19 '19 at 09:11
  • @amithm7 Yes. If `A::A(int)` is not explicit, then `char` can be first converted to `int` and then converted further to `A`. – L. F. May 19 '19 at 09:12