Why min still complains inside constexpr?

I have the following code snippet:

#include <iostream>
#include <type_traits>
#include <algorithm>
#include <cstdint>
using T = double;

int main()
{
    f();
}
void f() {
    T x = 2;
    if constexpr(std::is_integral_v<T>)
    {
        std::cout << std::min(static_cast<int64_t>(2), x);
    } else {
    std::cout << std::min(1.0, x);
    }
}

The compiler is explaining that

<source>:15:57: error: no matching function for call to 'min(int64_t, T&)'

I thought it won’t be a problem because when T is an double, the first branch won’t be instantiated. Apparantly my understanding is wrong. Could someone help point out where my understanding goes wrong?

Answer

You need to make f() template, and T template parameter.

template <typename T>
void f() {
    T x = 2;
    if constexpr(std::is_integral_v<T>)
    {
        std::cout << std::min(static_cast<int64_t>(2), x);
    } else {
    std::cout << std::min(1.0, x);
    }
}

then

int main()
{
    f<double>();
}

For constexpr if:

(emphasis mine)

If a constexpr if statement appears inside a templated entity, and if condition is not value-dependent after instantiation, the discarded statement is not instantiated when the enclosing template is instantiated .

Outside a template, a discarded statement is fully checked. if constexpr is not a substitute for the #if preprocessing directive:

void f() {
    if constexpr(false) {
        int i = 0;
        int *p = i; // Error even though in discarded statement
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *