# Thread: why aren't implicit type conversions transitive?

1. ## why aren't implicit type conversions transitive?

after a nice discussion with jdong on irc, we're wondering why..

Code:
```struct Number {
Number(const int &n) {
num = n;
}
int num;
};

Number foo = 42;

struct SpecialNumber {
SpecialNumber(const Number &n) {
num = n.num;
}
int num;
};

// this works fine
SpecialNumber bla1 = Number(42);

// won't compile
SpecialNumber bla2 = 42;```
..the second assignment at the end does not automatically cast to Number(42)?

<jdong> bazkie: but the TRUE question is, what does C++ mean from an OOP standpoint when it lets you say "Number n = 42" ?
as in, a
Number bla(42);
would seem logical: it's a number, initialized by some value.

however, a
Number bla = 42;
seems ugly: bla IS NOT an integer itself, so why does C++ allow this?

concluding, it's a 2-sided question:

1. if C++ allows the Number bla = 42 way of calling a constructor, shouldn't it allow for a SpecialNumber bla = 42 as well?

2. should not C++ disallow for both methods of calling a constructor for a more aesthetically sound OOP design?

2. Only one implicit type conversion by construction is allowed. The reason why is that the standard says so.

More practically, if multiple implicit constructor calls were allowed, there is a potential for ambiguity -- and even if there is no ambiguity, it could take the compiler a huge amount of effort to figure out which chain of conversions is the legal one.

Imagine say, ten types, with various constructors that convert from one type to another. The compiler must determine, not only which constructors to use, but the order in which to use them, to ultimately transform type A into type Z. The big-O complexity of this is, I believe, O(N!)

3. heh, exactly what i thought (thanks for confirming), but yet the second question remains thanks for your reply btw.

*edit: by the way:
Only one implicit type conversion by construction is allowed. The reason why is that the standard says so.
could you give me the paragraph/section number in ISO/IEC that proves that statement? we just like to see it to be sure

4. Originally Posted by bazkie
heh, exactly what i thought (thanks for confirming), but yet the second question remains thanks for your reply btw.
I think the second question starts from the wrong basis. There is no difference from a semantic standpoint between

Code:
`FooType a( bar );`
and

Code:
`FooType a = bar;`
Both will result in a call to a constructor. The second version gets people in the beginning because it looks like an assignment. The reason this was allowed is because variable initializations in C look like this, and it was decided for reasons I'm not privy to, that the identical syntax should be allowed for initialization of objects (at least, when there is only one argument to the constructor).

I'm guilty of using the second version much more often than the first. But I have no trouble remembering that it's a constructor call, not an assignment. Other people do (not to their detriment, it's a weird rule)

*edit: by the way:

could you give me the paragraph/section number in ISO/IEC that proves that statement? we just like to see it to be sure
Probably a better question for LaserLight to answer, since I don't have the entire thing memorized like he does

EDIT: In my previous example I said "ten types." In reality, the number of types is the total number of types in the entire program (at least what is visible from the current translation unit). The compiler must consider each possible chain of conversions, even if only just to produce an error that "this can't be done." A simple typo could result in a compile time of a thousand years.

5. 2. If you don't like = mark your constructors explicit. Originally I'm sure that fell under "don't unnecessarily annoy C programmers" but even now int a(5) just seems wrong.

Clause 12.3, paragraph 4, states
Originally Posted by ISO C++
At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.

6. Originally Posted by tabstop
2. If you don't like = mark your constructors explicit. Originally I'm sure that fell under "don't unnecessarily annoy C programmers" but even now int a(5) just seems wrong.
I think that even with explicit you can still use the assignment-looking syntax, but I'm too lazy to check. explicit prevents honest-to-God implicit conversions.

7. Originally Posted by brewbuck
I think that even with explicit you can still use the assignment-looking syntax, but I'm too lazy to check. explicit prevents honest-to-God implicit conversions.
If I try it I get
Code:
`interesting.cpp:11: error: conversion from ‘int’ to non-scalar type ‘Number’ requested`
with the code
Code:
```struct Number {
explicit Number(const int &n) {
num = n;
}
int num;
};

int main() {
// this works fine
Number foo = 42;
//
}```

8. That's because list initialization and assignment initialization are not the same.
Code:
```Number n(5); // -> construct n using Number(int) constructor
Number m = 5; // -> implicitly convert 5 to Number and initialize m with the resulting temporary```
in other words, the second statement is interpreted as
Code:
`Number m = Number(5);`
but only after validation, of course; i.e. an explicit constructor is not allowed. Besides, the implicit conversion could also use a conversion operator, i.e.
Code:
`Number m = someSpecialNumber;`
could be interpreted as
Code:
`Number m = someSpecialNumber.operator Number();`