3

in book "The Cpp standard library", 2nd edition, by Nicolai M. Josuttis, says (5.4, p.125) that definition of struct common type is following:

template <typename T1, typename T2>
struct common_type<T1,T2> {
typedef decltype(true ? declval<T1>() : declval<T2>()) type;
};

I have serious problems to believe that this is correct definition of common_type. Reason:

typedef decltype(true ? declval<T1>() : declval<T2>()) type;//As far as I understand this will always pick second operand, declval<T1>(), due to the fact that there is 'true' value. Am I right?
ildjarn
  • 62,044
  • 9
  • 127
  • 211
smallB
  • 16,662
  • 33
  • 107
  • 151
  • 3
    The expression is not actually evaluated, it just takes the types from it. – Some programmer dude Nov 07 '12 at 12:30
  • @JoachimPileborg yes, I understand it, but the ternary ?: will always return the operand on the left hand side of ':' if the value in front of '?' is true. – smallB Nov 07 '12 at 12:33
  • 2
    If might as well have been `false`, because the code is never run. Most likely there is never even any code generated for this. It's even an error to have [`std::declval`](http://en.cppreference.com/w/cpp/utility/declval) in code that is executed. – Some programmer dude Nov 07 '12 at 12:37
  • Keep in mind that even if this would be evaluated (which it isn't), the ternary operator expression doesn't automatically have the type of the returned operand, because that is only known at runtime (even if in this case the condition is a compile-time constant, but that's just a special case). So it has to be of some, well, common type of the two operands, for the type to be known at compile-time. – Christian Rau Nov 07 '12 at 13:02
  • Detail: This definition of `common_type` results in unintended behaviour in some cases, see [defect report DR2142](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2141). Yet, Eugene Mamin's answer is still correct. – dyp Nov 07 '12 at 21:05

1 Answers1

4

It's all about conditional operator. It isn't selection statement like if or switch.

5.16 paragraph of ISO C++11 standard:

Otherwise, if the second and third operand have different types and either has (possibly cv-qualified) class type, or if both are glvalues of the same value category and the same type except for cv-qualification, an attempt is made to convert each of those operands to the type of the other.

So, it doesn't matter that decltype contains true condition, compiler have to choose common type as result.

UPD: 5.16 contains further description of correct behavior, you should see it for completely understanding entire process. But for your particular question:

Using this process, it is determined whether the second operand can be converted to match the third operand, and whether the third operand can be converted to match the second operand. If both can be converted, or one can be converted but the conversion is ambiguous, the program is ill-formed. If neither can be converted, the operands are left unchanged and further checking is performed as described below. If exactly one conversion is possible, that conversion is applied to the chosen operand and the converted operand is used in place of the original operand for the remainder of this section.

Eugene Mamin
  • 749
  • 4
  • 8
  • Hi, thanks for your answer, the only problem I have is: an attempt is made to convert each of those operands to the type of the other. How would that work? Is compiler converting the type of left operand to the type of the right or vice versa? Are there any rules for it? – smallB Nov 07 '12 at 12:47