The last question I asked was something I stumbled upon when trying to understanding another thing... that I also can't understand (not my day).
This is quite a long question statement, but at least I hope this question might prove useful to many people and not only me.
The code I have is the following:
template <typename T> class V;
template <typename T> class S;
template <typename T>
class V
{
public:
T x;
explicit V(const T & _x)
:x(_x){}
V(const S<T> & s)
:x(s.x){}
};
template <typename T>
class S
{
public:
T &x;
explicit S(V<T> & v)
:x(v.x)
{}
};
template <typename T>
V<T> operator+(const V<T> & a, const V<T> & b)
{
return V<T>(a.x + b.x);
}
int main()
{
V<float> a(1);
V<float> b(2);
S<float> c( b );
b = a + V<float>(c); // 1 -- compiles
b = a + c; // 2 -- fails
b = c; // 3 -- compiles
return 0;
}
Expressions 1 and 3 work perfectly, while expression 2 does not compile.
If I have understood properly, what happens is:
Expression 1
- c is is implicitly converted to
const
by using a standard conversion sequence (consisting on just one qualification conversion). V<float>(const S<T> & s)
is called and a temporal theconst V<float>
object generated (let's call it t). It is already const-qualified because it is a temporal value.- a is converted to const similarly to c.
operator+(const V<float> & a, const V<float> & b)
is called, resulting in a temporal of typeconst V<float>
that we can call q.- the default
V<float>::operator=(const & V<float>)
is called.
Am I OK up to here? If I made even the most subtle mistake please, let me know, for I am trying to gain an understanding about implicit casting as deep as possible...
Expression 3
- c is converted to
V<float>
. For that, we have a user-defined conversion sequence:
1.1. first standard conversion:S<float>
toconst S<float>
via qualification conversion.
1.2. user-defined conversion:const S<float>
toV<float>
viaV<float>(const S<T> & s)
constructor.
1.3 second standard conversion:V<float>
toconst V<float>
via qualification conversion. - the default
V<float>::operator=(const & V<float>)
is called.
Expression 2?
What I do not understand is why there is a problem with the second expression. Why is the following sequence not possible?
- c is converted to
V<float>
. For that, we have a user-defined conversion sequence:
1.1. initial standard conversion:S<float>
toconst S<float>
via qualification conversion.
1.2. user-defined conversion:const S<float>
toV<float>
viaV<float>(const S<T> & s)
constructor.
1.3. final standard conversion:V<float>
toconst V<float>
via qualification conversion. - Steps 2 to 6 are the same as in case of expression 1.
After reading the C++ standard I though: 'hey! maybe the problem has to to with 13.3.3.1.2.3!' which states:
If the user-defined conversion is specified by a template conversion function, the second standard conversion sequence must have exact match rank.
But that cannot be the case since the qualification conversion has exact match rank...
I really have no clue...
Well, whether you have the answer or not, thanks you for reading up to here :)
See Question&Answers more detail:os