2

I have a file a.cpp:

#include <bits/stdc++.h>

using namespace std;

int main(){
    int a=5;
    double b=4.3;
    decltype(a>b?a:b) n;
    cout << typeid(n).name();   
}

The Output of above Code is d but I expect it to be i as "a" is greater than "b"

I am trying to learn about decltype. Can you please tell what I am missing here?

I am using gcc version 6.3.0 (MinGW.org GCC-6.3.0-1).

Al.G.
  • 3,929
  • 6
  • 32
  • 52
  • 6
    It doesn't matter what's greater, the type of the expression is double either way. – tkausl Dec 22 '19 at 15:10
  • 2
    C++ is a statically-typed language. – Evg Dec 22 '19 at 15:10
  • What you want would only work if the two arguments are constexpr, [like so](http://coliru.stacked-crooked.com/a/293fe0a38c8c8997), I fail to see the use case though. – Borgleader Dec 22 '19 at 15:16
  • Does this answer your question? [Implicit type conversion rules in C++ operators](https://stackoverflow.com/questions/5563000/implicit-type-conversion-rules-in-c-operators) – Borgleader Dec 22 '19 at 15:19
  • `template auto max(T1 a, T2 b) -> decltype(a>b?a:b) { return a>b?a:b;}` how does this code work then? – PrashantKumarNirmal Dec 22 '19 at 15:22
  • **Recommended reading:** [Why should I not #include ?](https://stackoverflow.com/q/31816095/560648) – Lightness Races in Orbit Dec 22 '19 at 15:23
  • @tkausl Write your answer in the answer section please – Lightness Races in Orbit Dec 22 '19 at 15:24
  • [The type and value category of the conditional expression `E1 ? E2 : E3` are determined according to the following rules: ...](https://en.cppreference.com/w/cpp/language/operator_other#Conditional_operator) – Evg Dec 22 '19 at 15:24
  • 1
    @PrashantKumarNirmal That function causes undefined behavior if it is called with arguments of the same type and its return value (which will be a reference to one of the parameters out-of-their lifetime) is used. You should not use it. You need to remove the trailing return type to make it behave correctly. In either case, it returns a compile-time fixed type, determined by the rules that are described, e.g. [here](https://en.cppreference.com/w/cpp/language/operator_other#Conditional_operator). – walnut Dec 22 '19 at 15:56
  • @Borgleader I don't think it's a duplicate of *that* question, because this one asks about conditionally selecting a type and not about int/float type promotion. The essence of this question will remain the same if you convert one of the types to a struct type, and the other question is not about this. – Al.G. Dec 22 '19 at 16:55
  • 1
    As an aside, regarding the thing that @walnut describes, this is true and it's the reason that I (and many others) feel that C++ is just completely out of control for the average user. It really should not be that trivial to get silent, yet critical, bugs. – Lightness Races in Orbit Dec 22 '19 at 16:58
  • 1
    @LightnessRacesBY-SA3.0 Clang gives a [warning](https://gcc.godbolt.org/z/V7wiEu), at least. Surprisingly, GCC does not. – HolyBlackCat Dec 22 '19 at 17:02
  • @Al.G. I added that duplicate after OP posted a comment asking why the type of the expression was always double (that comment seems to have since been removed). – Borgleader Dec 22 '19 at 17:17
  • That's why we don't vote-to-close-as-duplicate based on comments, but on the actual content of the question. – Lightness Races in Orbit Dec 23 '19 at 02:41

1 Answers1

3

C++ is a statically-typed language.

That means, the type of a thing cannot depend on runtime criteria.

For this reason, the expression a>b?a:b will always evaluate to a value of the same type. That's part of the rules of the conditional operator.

In this case, the "mutually compatible type" (I have made this term up) is double, so you will always get a double (see the rules here).

If a wins the condition, it's converted from int to double, except in decltype your code is an "unevaluated context" (because nothing at runtime can possibly influence the outcome), so the condition isn't even performed, only the possible resulting type is calculated, from the types of the arguments to the conditional operator. If there were multiple possible resulting types, then the code would be ambiguous and your program would not be compilable.

You can get this behaviour with magic like std::variant, but consider whether you really need/want it.

Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989