In reference to this question. The core constant expression that is used to initialize the
constexpr
y
if
if constexpr
template <typename T>
void foo() {
constexpr int x = -1;
if constexpr (x >= 0){
constexpr int y = 1 << x;
}
}
int main(){
foo<int>();
}
error: right operand of shift expression '(1 << -1)' is negative [-fpermissive]
constexpr
template <typename T>
void foo(){
constexpr int x = -1;
constexpr auto p = []() constexpr { return x; };
if constexpr (x >= 0){
constexpr int y = 1<<p();
}
}
constexpr
y
The standard doesn't say much about the discarded statement of an if constexpr
. There are essentially two statements in [stmt.if] about these:
Neither of these applies to your use: the compilers are correct to complain about the constexpr
if initialisation. Note that you'll need to make the condition dependent on a template parameter when you want to take advantage of the instantiation to fail: if the value isn't dependent on a template parameter the failure happens when the template is defined. For example, this code still fails:
template <typename T>
void f() {
constexpr int x = -1;
if constexpr (x >= 0){
constexpr int y = 1<<x;
}
}
However, if you make x
dependent on the type T
it is OK, even when f
is instantiated with int
:
template <typename T>
void f() {
constexpr T x = -1;
if constexpr (x >= 0){
constexpr int y = 1<<x;
}
}
int main() {
f<int>();
}