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 wouldn't be a problem because when T is a double, the first branch won't be instantiated. Apparently my understanding is wrong. Could someone help point out where my understanding goes wrong?
std::min and std::max are constexpr in C++14, which obviously means there isn't a good reason (these days) not to have them constexpr.
It means that compiler makes most general assumptions when compiling this function. And this assumption is that arguments are non-compile-time. It means that compiler can't guarantee that your if-constexpr is always compile-time, hence the error about it.
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 } }
Outside of a template, the "false" branch of a constexpr if
clause is discarded, not ignored. Thus, the code in such a branch must still be well-formed (and yours isn't, for the reason given).
From cppreference:
Outside a template, a discarded statement is fully checked.
if constexpr
is not a substitute for the #if preprocessing directive.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With