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 } }