In this code:
template<class T>
struct Side
{
};
template<class T>
struct LeftSide : public Side<T>
{
};
template<class T>
struct RightSide : public Side<T>
{
};
Side<int>* f(int left, int right)
{
return left < right ? new LeftSide<int> : new RightSide<int>;//<---Here I'm returning either left or right side
}
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
I’m getting an error:
_Error 1 error C2446: ‘:’ : no conversion from ‘RightSide *’ to ‘LeftSide *’_
I’ve thought (wrongly as I see) that I can assign pointer from derived to base without any problems. So where is the problem?
The problem is not with the conversion from either
LeftSideorRightSidetoSide<T>. As you originally thought, this conversion would be fine.Rather, the problem is with this expression:
Let’s break this down a little. The ternary operator (properly referred to in the Standard as the ‘comparison operator’) looks like this:
Keep in mind that this whole construct is itself an expression. Meaning it returns a value, which has to have a type, obv. The type of the whole expression is deduced from the types of
lhs_expressionandrhs_expression. In this case, you have aLeftSideand aRightSide. So, here’s your problem.LeftSideandRightSideare not directly related to each other other than having a common base class, and there’s no conversion available between them. (You’d have to write one.) So there’s no single datatype that thebool_val ? lhs_expression : rhs_expressioncan have. You might think, “well, silly compiler, why not just figure out the common base class and use that?” This is, indeed, a bit of a pain. Leaving the argument of it being Right or Wrong aside, it just doesn’t work that way.You have two options.
One, use a simpler construct:
Two, if you really really want to use the ternary operator (which is the case sometimes), you need to spoon-feed the compiler it’s datatypes: