2
votes

Consider the following class definitions of A and B:

class A {
public:
   void func() const {}
};

class B {
public:
   // user-defined conversion operator to A
   operator A() const { return a_; }
private:
   A a_;
};

The class A defines a public member function called func(). The class B does not, but it does define a user-defined conversion operator to the type A. This way, an instance of B can be converted into an instance of A. The following code works as expected:

B b;
static_cast<A>(b).func(); // call func() on temporary instance of A

In the code above, the conversion operator is implicitly called by means of the static_cast named cast.

Note that the conversion operator in B is not specified as explicit in order to allow implicit conversions as well. However, the following code does not compile:

B b;
b.func(); // <-- error: 'class B' has no member named 'func'

Just as the error message says, class B has no member named func, but class A does, and class B does have a user-defined conversion operator to A. The user-defined conversion operator is not implicitly called in this case.

Why is the conversion not being implicitly done?

1
What if it has 30 conversions operators? Should a compiler try all of them? And what if it can be converted to two types that both have that method? How could a compiler guess what you are trying to do exactly? Pretend that you are explicit about your intents make sense indeed. - skypjack
@skypjack yes, I think the compiler should try all of them and only generate an error message if there is an ambiguity. - 里纳尔迪
Then fortunately the committee decided differently. ;-) - skypjack
It's an interesting thought experiment, though, to consider the implications of a compiler trying all possible conversions. - AndyG
@skypjack That's a strange argument. If you write b(1) or b+1 etc., the compiler will in fact try all 30 conversion operators. There's just something different about the . operator. - aschepler

1 Answers

5
votes

Conversion isn't considered for member access (§5.2.5/2 [expr.ref]).

In either case, the id-expression shall name a member of the class or of one of its base classes

Here the id-expression is func()

So the compiler considers that func must be a member of B or a class that B derives from. Implicit conversion to other types that might have a func member is not considered.