(with explicit) Priority with operator and constructor conversion

I looked through a lot of questions related to the conversion, but it seems that none of them discussed the explicit keyword in this way. Here is the code:

struct B; struct A{ /*explicit*/ A(const B&){ cout << 1; } // *1 }; struct B{ /*explicit*/ operator A()const{ cout << 2; } // *2 }; void foo(const A &){} int main(void){ B b; foo( /*static_cast<A>*/ (b) ); // *3 } 

Result: (Y: uncommented, N: commented, X: either)

 # | *1 | *2 | *3 |output| 1 | N | N | N |error | 2 | N | N | Y | 1 | 3 | N | Y | N | 1 | 4 | N | Y | Y | 1 | 5 | Y | N | N | 2 | 6 | Y | N | Y | 1 | 7 | Y | Y | N |error | 8 | Y | Y | Y | 1 | 

1, 7 are errors that are normal (ambiguous and automatic conversion)
2 the constructor seems to have a higher priority, but why?
3, 5 is easy to understand.
4 is strange since it does not cause explicit. why?
6 may be called by an explicit or higher priority constructor. What reason? 8 it looks like the constructor has a higher priority, but why?

Can someone offer some explanation? Thanks!

+7
c ++ explicit type-conversion
source share
1 answer

Very good question.

First of all, the explicit element does not mean "this takes precedence if explicit conversion is required." This means that "this thing can be called explicitly." Thus, he creates some situations when he cannot be called, but does not make him called in other situations.

Another thing to keep in mind is that static_cast is direct initialization , and passing an argument to a function is copy initialization . Among other things, copy initialization never uses explicit constructors. Another thing to note is that direct initialization requires the use of constructors for classes (explicitly or not). Although this does not mean that the conversion cannot perform direct initialization: it can be used to convert the constructor argument, and if the constructor is a copy generated by the compiler, then it will look like a conversion function executed with direct initialization (whereas in fact it did copy constructor). Try to declare the copy constructor without defining it (the disable-copy method), and you will see that the conversion function no longer works in the context of direct initialization: it will compile, but will lead to a binding error.

With that in mind:

  • The obvious.
  • Direct initialization requires a constructor, so it is called.
  • The obvious.
  • Same as 2, really. Declaring the conversion function explicit only prevents it from being implicitly turned off; it does not force it to be used in explicit contexts.
  • The obvious.
  • Again, direct initialization requires a constructor, and it allows you to use explicit ones.
  • The obvious.
  • Another direct case of initialization.
+2
source share

All Articles