One of the subjects which I was pursuing recently, was not just of why, before March of 2019, I had gotten some error messages, when trying to compile a certain program, but also of why or if, other people, using other types of computers, might continue to obtain error messages, long after I was no longer obtaining them.
And a basic concept which I had referenced was that C++ compilers, when not given an exact match in the data-types of a function prototype, to the data-type of the arguments passed to those functions, will first try to perform a type-conversion which is referred to as a “promotion”, and if that fails, will attempt what’s referred to as a “standard conversion”, the latter of which can transform a ‘higher’ type of built-in number to a ‘lower type’, etc.. There was a basic question which I had not provided any sort of answer to, nor which I even acknowledged explicitly could exist. That question has to do with what happens, when more than one type-conversion has the ability to go from the argument-type, to the parameter-type of a function prototype.
Theoretically, it would be possible to design a compiler such, that every time a type-conversion is being sought, both types are tried, in a pattern which is referred to as ‘recursion’, but which can also just be referred to as an ‘exhaustive search’. There’s every possibility that this is not how the compiler is programmed in fact. What can happen instead would be, that the compiler is willing to perform a promotion, in the service of a potential, standard conversion, but that it will go no further.
And in that context, as well as in the mentioned context of recursive template definitions, casting a derived class to one of its parent classes, counts as a promotion.
There’s every possibility that if recursion was placed in the code of the compiler, to re-attempt a standard conversion, to execute prior to another standard conversion that will not fit yet, the result could become some sort of endless loop, while the real behaviour of a compiler needs to be more stable. And this would be a valid reason, for which certain standard template declarations will first try to instantiate the templates using a ‘float’, then a ‘double’, and then a ‘long double’, in the form of specializations. The programmers will assume that a standard conversion needs to receive a value, that can be the result of a promotion. And in that case, the first template specialization may not work, while a later one might, just because to convert, say, a ‘double_t’ to a ‘long double’ will be a promotion, while to convert a ‘double_t’ to a ‘float’ would not, but would in fact be a standard conversion, in the service of another, standard conversion (that should not happen).