Reputation: 29
Here is the code which has unexpected behaviour:
#include<iostream>
using namespace std;
namespace n1{
namespace n2{
enum comparator_t {
LT = 0, /*!< less-than < */
LE = 1, /*!< less-than-or-equal-to, i.e. <= */
};
}
}
int main(){
int32_t const INF_VALUE = INT32_MAX >> 1;
int32_t const MINUS_INF_VALUE = INT32_MIN >> 1;
int32_t const LT_INFINITY = (INF_VALUE << 1) | n1::n2::LT;
int32_t const LE_MINUS_INFINITY = (MINUS_INF_VALUE << 1) | n1::n2::LE;
int32_t const LE_ZERO = (0 << 1) | n1::n2::LE;
static_assert(LE_ZERO != LT_INFINITY, "");
static_assert(LE_ZERO != LE_MINUS_INFINITY, "");
}
The above C++ code gives a compilation error:
error: non-constant condition for static assertion
However, when the last line of the code is commented (//static_assert(LE_ZERO != LE_MINUS_INFINITY, "");
), the code compiles properly. The definition of LE_MINUS_INFINITY
and INF_VALUE
look very similar, so why is the code not compiling?
Upvotes: 2
Views: 79
Reputation: 51825
The problem is with this line:
int32_t const LE_MINUS_INFINITY = (MINUS_INF_VALUE << 1) | n1::n2::LE;
Up until the C++20 Standard, left-bit-shifting a negative signed integer value is undefined behaviour. Your compiler (rightly) refuses to accept the result of that UB as a compile-time constant.
Changing to use the -std=c++20
(or equivalent, for your compiler) fixes the issue. See on Compiler Explorer.
Upvotes: 4