3

I want to fully understand conversions, i.e. to be sure I know when does a function call would cause an implicit conversion, and when would it cause a compilation error. I've learnt that a conversion may be done if and only if there is a singular way to convert the variable with up to two steps from the following list (sorted by priority):

1. Exact match
2. Promotion
3. Conversion
4. User defined conversion

Where, the way I understood it (you may correct me), is that promotion is a conversion of primitives into bigger primitive types, such as short to int, float to double, etc; Conversion is any conversion between primitives which isn't promotion, such as int to char, etc; And user defined conversions are conversions of classes using conversion constructors and conversion operators. Now, I also know that inheritance means and Is-A relationship, meaning that a derived class is base class, and so sending a derived class to a function which expects a reference to a base class should work. Combining the two concepts above, we should get that the following example I wrote, should work:

class C {};
class D: public C
{
public:
D(int x){}
};
void f(C& c) {}
f(3);

Since D can be converted-to from int, and a D is a C. But this code isn't being compiled. Why is that? How can the contradiction be resolved? Can you shed some light on the matter? Thanks!

curiousguy
  • 8,038
  • 2
  • 40
  • 58
Idan
  • 5,365
  • 5
  • 24
  • 28

1 Answers1

5

The code doesn't compile because the conversion would create a temporary, which can't bind to a non-const reference.

If you pass the parameter by const reference (or by value, but I'm not suggesting you do that), it will work.

You also need a conversion constructor in the base class (explained below).

class C {
public:
   C(int x){}
};
class D: public C
{
public:
   D(int x):C(x){}
};

void f(const C& c) {}
f(3);

This is because implicit conversion only applies a maximum of one times. In your case, there is a direct conversion from int -> D and one from D -> C, so an int can't implicitly be converted to C.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • @Als I didn't see the base class. If he has a conversion ctor in the base class, it will. – Luchian Grigore Jun 26 '12 at 08:36
  • You are totally right about the const thing. But are you sure about the "implicit conversion only applies a maximum of one times"? I've been taught that an implicit conversion applies up to two times. – Idan Jun 26 '12 at 08:47
  • @Idan yes. It can't (logically). Any restriction greater than 1 would yield ambiguities. – Luchian Grigore Jun 26 '12 at 08:50
  • @Idan see here - http://stackoverflow.com/questions/867462/c-implicit-conversions – Luchian Grigore Jun 26 '12 at 08:51
  • from the link you've attached, it seems like only 1 *user-defined* conversion is allowed, but more native conversions are allowed. So in this case it should work (with my example with an added 'const'), and it does. – Idan Jun 26 '12 at 09:17
  • It doesn't work by value though and I don't understand why. From what I've understood it should work, as D can be converted to from int, and D can be sliced into C using the copy constructor. – Idan Jun 26 '12 at 09:21
  • @Idan at most one **user-defined** implicit conversion is allowed per conversion sequence. Many implicit conversions involve more than one "elementary" conversion, f.ex. `Der*` to `const Base*` involves a derived-to-base and a non-const-to-const conversion. – curiousguy Jul 22 '12 at 00:44