4

I have a code:

struct Conv;
struct Test {
    Test() {}
    Test(Test const& ref) = delete;
    Test(Test&& ref) = delete;
    Test(int) { puts("int"); }
};

struct Conv {
    explicit operator int() const {
        puts("operator Test()");
        return 7;
    }
};

int main() {
   Conv y;
   Test x {y}; // direct list initialization
}

It produces error:

clang: no matching constructor for initialization of 'Test' Test x {y};

gcc: no matching function for call to 'Test::Test(<brace-enclosed initializer list>)' 21 | Test x {y};

If I change from int() to Test(), the code works

struct Conv {
    explicit operator Test() const {
        puts("operator Test()");
        return 7;
    }
};

This works. If marked explicit compiler shouldn't do any implicit conversions? But why the second case works whereas the first doesn't?

Vegeta
  • 461
  • 2
  • 6
  • 1
    It's `explicit` so `Test x {static_cast(y)};` ? – Ted Lyngmo Jun 17 '21 at 07:17
  • 1
    Since you marked the conversion operator as `explicit` you must use explicit conversion (e.g. `static_cast(y)`) for it to work. – Some programmer dude Jun 17 '21 at 07:17
  • I suggest you look in the right column on the "Related" questions, where you have [What does the explicit keyword mean?](https://stackoverflow.com/questions/121162/what-does-the-explicit-keyword-mean?rq=1) – Some programmer dude Jun 17 '21 at 07:18
  • 1
    Then why the `operator Test()` works – Vegeta Jun 17 '21 at 07:19
  • 1
    Because you are explicitly constructing a `Test` from `y` – Alan Birtles Jun 17 '21 at 07:24
  • 5
    @Vegeta, There's no "obvious" (explicit) conversion to `int` in `Test x {y};`, but there is an "obvious" conversion to `Test` in there. By putting `explicit` in a conversion operator, you're saying that every time this conversion is used, it should be "obvious" (explicit) in the code that uses it that this conversion is happening. – chris Jun 17 '21 at 07:31
  • Sorry for the late reply. Thanks for all the answers. – Vegeta Jun 18 '21 at 11:10

1 Answers1

3

why the operator Test() works? Because explicit operator declares a user-defined conversion function that participates in direct-initialization and explicit conversions only:

Test x1 {y};    // direct initialization  OK
Test x2 = static_cast<Test>(y);  // explicit conversion OK
//Test x3 = y;  // copy initialization Error
alex_noname
  • 26,459
  • 5
  • 69
  • 86