#include <iostream>
struct A {
A(const A&) { std::cout << "A::A(const A&)" << '\n'; }
A() { std::cout << "A::A()" << '\n'; }
A(int) { std::cout << "A::A(int)" << '\n'; }
};
struct B {
explicit operator A() const { std::cout << "explicit B::operator A() const" << '\n'; return A{}; }
B() { std::cout << "B::B()" << '\n'; }
};
int main(){
B b;
A a(b);
}
B::B()
explicit B::operator A() const
A::A()
A::A(const A&)
A::A(const A&)
#include <iostream>
struct A {
A(const A&) { std::cout << "A::A(const A&)" << '\n'; }
A() { std::cout << "A::A()" << '\n'; }
A(int) { std::cout << "A::A(int)" << '\n'; }
};
struct B {
explicit operator int() const { std::cout << "explicit B::operator int() cont" << '\n'; return 1; }
B() { std::cout << "B::B()" << '\n'; }
};
int main(){
B b;
A a(b);
}
As a general (approximate) rule of thumb, you only get to use an explicit conversion function if you explicitly name the type you're converting to. So you can use 'explicit operator int' to convert to 'int' but not to 'A'.In this specific case, we consider constructors of 'A' (including explicit ones, because we're using direct-initialization). For the desired 'A(int)' constructor, we try to form an implicit conversion sequence from 'b' to its parameter type 'int'. Implicit conversion sequences model copy-initialization (just like copy-initialization will be used to initialize the parameter from the argument if the constructor is selected). And copy-initialization doesn't get to use explicit conversion functions (see [over.match.conv]/1.1).
On Friday, September 2, 2016 at 6:18:17 PM UTC-3, Richard Smith wrote:As a general (approximate) rule of thumb, you only get to use an explicit conversion function if you explicitly name the type you're converting to. So you can use 'explicit operator int' to convert to 'int' but not to 'A'.In this specific case, we consider constructors of 'A' (including explicit ones, because we're using direct-initialization). For the desired 'A(int)' constructor, we try to form an implicit conversion sequence from 'b' to its parameter type 'int'. Implicit conversion sequences model copy-initialization (just like copy-initialization will be used to initialize the parameter from the argument if the constructor is selected). And copy-initialization doesn't get to use explicit conversion functions (see [over.match.conv]/1.1).Thanks for your reply. Let me just check if I'm following you correctly. You're basically saying that, notwithstanding the fact that the initialization A a(b); is a direct-initialization, the compiler considers the initialization of the parameter in the constructor A(int) to be a copy-initialization, and because of this, an explicit conversion function is not accepted. Is that correct?
Also in [over.match.conv]/2 we have: " [ Note: This argument will be compared against the implicit object parameter of the conversion functions. — end note ]" the implicit doesn't seem to be correct. Could you clarify?