Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do the following two declarations involving automatic return type work the same? If so, why?

Tags:

c++

c++11

c++14

I'm confused why the book I'm reading says that the following two declarations have the same effect:

template<typename T1, typename T2> auto max (T1 a, T2 b) -> decltype(b<a?a:b);

template<typename T1, typename T2> auto max (T1 a, T2 b) -> decltype(true?a:b);

In the first declaration, the return type of max(a, b) could be the type of a, or the type of b. In the second declaration, the return type is the type of a. How can the two declarations have the same effect?

Here is the passage that I read:

enter image description here

enter image description here

like image 217
megamonium Avatar asked Dec 20 '18 04:12

megamonium


3 Answers

In the second declaration, the return type is the type of a.

On what do you base that assumption? I think this is the source of the confusion. The evaluated static type of a ternary expression (or of any expression) does not depend on any semantic analysis of the values of the operands, only on the types of the operands. The types of all three ternary operands are the same in both expressions, thus the deduced type is the same.

In other words, the fact that the conditional operand is true which, at runtime, would cause the expression to evaluate to a, is completely irrelevant with regard to static type analysis and deduction.

like image 110
TypeIA Avatar answered Oct 19 '22 01:10

TypeIA


Like the passage says, the type of max(a, b) is the common type of a and b since the conditional operator (E1 ? E2 : E3) returns the common type of the second and third operands.

like image 43
David G Avatar answered Oct 19 '22 02:10

David G


They do not, but for a different reason.

An expression's type is a static construct. It does not depend on the value of its operands. If the expressions are valid, b < a ? a : b, true ? a : b and false ? a : b all have the same type, determined from the types of a and b through a complex set of rules that takes up about 1.5 pages in the standard.

They do have different SFINAE effects. If you pass a pair of arguments that do not actually support < comparison, then the first declaration will remove itself from overload resolution, while the second declaration will happily accept the arguments and then trigger a hard error when the function body is instantiated. This only really matters if you have a different max overload that could accept these arguments or if you have code inspecting the validity of an expression calling max.

like image 6
T.C. Avatar answered Oct 19 '22 02:10

T.C.