Home > Back-end >  C decltype evaluate wrong type
C decltype evaluate wrong type

Time:05-01

I have the function which type the same as minimal argument:

#include <iostream>

template<typename A, typename B>
auto Min(A a, B b) -> decltype(a < b ? a : b)
{
    return a < b ? a : b;
}
 
int main()
{
    auto b = Min(5, 2.0f); // float
    auto a = Min(5, 6.0f); // also float ?!
    std::cout << typeid(a).name() << std::endl;
    std::cout << typeid(b).name() << std::endl;
    std::cin.get();
}

But actuale I've got float for a and b. And my console print looks like: float float

Why the second function return type evaluating also as float ?

CodePudding user response:

The conditional operator (?:) can only yield a single type. In your case, int and float share the common type float, so that is the type the expression will yield.

If you don't want that, you'll need to move your code from being executed at run time and move it into being executed at compile time. Doing that allows you to return different types depending on the conditions at compile time. That would give you a min function like:

template<auto a, auto b> auto min()
{
    if constexpr(a < b) 
        return a;
    else
        return b;
}

In the above code, if the if constexpr is false, the whole return a; is discarded and the entire body of the function become return b; and if it is true, the opposite happens and your left with just return a;. This allows the function to return the type and value of the minimum object.

making this change to your code will give you

#include <iostream>

template<auto a, auto b> auto min()
{
    if constexpr(a < b) 
        return a;
    else
        return b;
}
 
int main()
{
    auto b = min<5, 2.0f>(); // float
    auto a = min<5, 6.0f>(); // int
    std::cout << typeid(a).name() << std::endl;
    std::cout << typeid(b).name() << std::endl;
    std::cin.get();
}

which ouputs

i
f

as seen in this live example

  •  Tags:  
  • c
  • Related